刷题 | 数组移动元素
Posted 就良同学
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题 | 数组移动元素相关的知识,希望对你有一定的参考价值。
题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
解法1
算法思想:
- 创建一个数组tmps用于存储nums中所有的非零元素(按原有顺序存储),遍历nums,将非零元素存于tmps中。
- 遍历tmps,将tmps中元素覆盖nums元素(从0号下标开始依次覆盖)。
- 将nums剩余位置元素置零。
时间复杂度=O(n)
空间复杂度=O(n)
代码实现:
#include <iostream>
#include <vector>
using namespace std;
class Solution
public:
void moveZeroes(vector<int>& nums)
vector<int> tmps;
int i;
for(i = 0; i < nums.size(); i++)
if(nums[i] != 0)
tmps.push_back(nums[i]);
for(i = 0; i < tmps.size(); i++)
nums[i] = tmps[i];
for(; i < nums.size(); i++)
nums[i] = 0;
;
int main()
int arr[] = 0, 1, 0, 3, 12;
vector<int> vec(arr, arr + sizeof(arr) / sizeof(int));
Solution().moveZeroes(vec);
for(int i = 0; i < vec.size(); i++)
cout << vec[i] << " ";
cout << endl;
system("pause");
return 0;
运行效果:
1 3 12 0 0
解法2
算法思想:
原地操作,不开辟新的内存空间
-
声明两个指针i和k,i:用于遍历数组,k:保证[0...k)中保存所有当前已遍历过的所有非0元素;
即:遍历完第i个元素后,[0...i]中所有非0元素都按照原有顺序排列再[0...k)中。
-
若当前元素nums[i]为0元素,忽略,继续向前遍历;
-
若当前元素nums[i]为非0元素,将该元素插入到nums[k]的位置,然后i++,k++;
-
重复上述操作,直至指针i遍历结束;
-
从位置k开始遍历数组,将元素值置零。
代码实现:
class Solution
public:
void moveZeroes(vector<int>& nums)
int i, k = 0;
for(i = 0; i < nums.size(); i++)
if(nums[i] == 0)
continue;
else
nums[k++] = nums[i];
for(i = k; i < nums.size(); i++)
nums[i] = 0;
;
相当于把数组nums分成左右两部分:
- 左部分:已处理元素集合,存储数组中已经处理完毕的非零元素(处理完毕即元素均为非0元素且按原有顺序排列),左右边界为[0...k),初始时k=0代表左部分为空;
- 右部分:待处理元素集合,左右边界为[k...nums.size()-1],初始时k=0代表整个数组。
解法3:
算法思想:
在解法2的基础上进一步优化,去掉解法2最后一步将数组剩余元素置零的操作。
-
声明两个指针i和k,i:用于遍历数组,k:保证[0...k)中保存所有当前已遍历过的所有非0元素;
即:遍历完第i个元素后,[0...i]中所有非0元素都按照原有顺序排列再[0...k)中。
-
若当前元素nums[i]为0元素,忽略,继续向前遍历;
-
若当前元素nums[i]为非0元素,将该元素与nums[k]对应元素交换位置,然后i++,k++;
-
重复上述操作,直至指针i遍历结束;
代码实现:
class Solution
public:
void swap(int &a, int &b)
int tmp = a;
a = b;
b = tmp;
void moveZeroes(vector<int>& nums)
int i, k = 0;
for(i = k; i < nums.size(); i++)
if(nums[i] == 0)
continue;
else
swap(nums[k++], nums[i]);
;
进一步优化:
若数组nums全是非零元素,按照上述代码,每个元素(均为非0元素)都会和自己执行一次交换,耗时。
class Solution
public:
void swap(int &a, int &b)
int tmp = a;
a = b;
b = tmp;
void moveZeroes(vector<int>& nums)
int i, k = 0;
for(i = k; i < nums.size(); i++)
if(nums[i] == 0)
continue;
else
if(nums[k] == 0)
swap(nums[k++], nums[i]);
else
k++;
;
相似题目
leetcode.27. 移除元素
class Solution
public:
int removeElement(vector<int>& nums, int val)
int k = 0;
for(int i = k; i < nums.size(); i++)
if(nums[i] != val)
nums[k++] = nums[i];
return k;
;
leetcode.26. 删除有序数组中的重复项
/*
算法思想:
声明指针k,将数组划分成两部分:nums[0...k)为已处理序列,nums[k...]为待处理序列,k初始时为0
声明指针i遍历数组:
1. 若已处理序列为空(即k==0),则将当前元素nums[i]插入到k位置,并执行k++;
2. 若已处理序列非空,将当前元素nums[i]与已处理序列尾元素nums[k-1]比较:
(1)若二者相等,忽略当前元素,继续遍历;
(2)若二者不等,将当前元素nums[i]插入到k位置,并执行k++。
*/
class Solution
public:
int removeDuplicates(vector<int>& nums)
int k = 0;
for(int i = 0; i < nums.size(); i++)
if(k == 0)
nums[k++] = nums[i];
else
if(nums[i] != nums[k-1])
nums[k++] = nums[i];
return k;
;
leetcode.80. 删除有序数组中的重复项 II
将leetcode.26中的nums[i] != nums[k-1]
改为nums[i] != nums[k-2]
即可。
class Solution
public:
int removeDuplicates(vector<int>& nums)
int k = 0;
for(int i = 0; i < nums.size(); i++)
if(k == 0)
nums[k++] = nums[i];
else
if(nums[i] != nums[k-2])
nums[k++] = nums[i];
return k;
;
LeetCode刷题(127)~最小移动次数使数组元素相等动态规划|数学
题目描述
给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数。每次移动将会使 n - 1 个元素增加 1。
示例:
输入:
[1,2,3]
输出:
3
解释:
只需要3次移动(注意每次移动会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
解答
Demo【n-1个元素都+1相对于 一个元素-1】
int minMoves(vector<int>& nums)
sort(nums.begin(),nums.end());
int count=0;
for(int i=nums.size()-1;i>0;--i)
count+=nums[i]-nums[0];
return count;
运行结果
Demo
int minMoves(vector<int>& nums)
int ans=0;
int a=INT_MAX;
for(int num:nums)
a=min(num,a);
for(int num:nums)
ans+=num-a;
return ans;
运行结果
Demo(动态规划)
int minMoves(vector<int>& nums)
sort(nums.begin(),nums.end());
int moves=0;//总的移动数量
for(int i=1;i<nums.size();++i)
int diff=moves+nums[i]-nums[i-1];//每次的移动数
nums[i]+=moves;
moves+=diff;
return moves;
运行结果
题目来源
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements
以上是关于刷题 | 数组移动元素的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode刷题100天—283. 移动零(双指针)—day20