题目:
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
链接:https://leetcode-cn.com/problems/move-zeroes
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
来源:力扣(LeetCode)
方法一:
新开辟空间 (O(n) ,O(n) )
解析:
将原数组中的非零元素全部拷贝到新数组中,然后将非零元素倒回原数组,最后把其余空位补零。
代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
vector<int> NoZeroNums;
for(int i = 0; i < nums.size(); i++)
if(nums[i])
NoZeroNums.push_back(nums[i]);
for(int i = 0; i <NoZeroNums.size(); i++)
nums[i] = NoZeroNums[i];
for(int i =NoZeroNums.size(); i <nums.size();i++)
nums[i] = 0;
}
};
方法二:
不开辟新空间 (O(n) ,O(1) )
解析:
原地操作,从前往后走,重写整个数组,用非零元素覆盖前面的元素。设立两个指针从前往后遍历,快指针指向刚遍历到的非零元素,慢指针指向当前该覆盖的位置;快指针走到头的时候就把其余位置写零。
代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0;
for(int i = 0; i < nums.size(); i ++ )
if(nums[i]){
nums[k] = nums[i];
k++;
}
for(int i = k; i < nums.size(); i++)
nums[i] = 0;
}
};
优化方法二:
解析:
用交换元素代替覆盖元素,省去最后补零的步骤。
代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0;
for(int i = 0; i < nums.size(); i ++ )
if(nums[i]){
if(i != k){ //只有在前面出现0时才交换
swap(nums[k], nums[i]); //直接交换元素,不需要最后补零
k++;
}
else
k++;
}
}
};