题目描述
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数。
解法1:双指针,第一个0与其后第一个非0匹配交换
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int len = nums.size();
int first0 = -1; //无效的初始index
for (int i = 0; i < len; ++i)
if (0 == nums[i]) {
if (first0 < 0) //寻找第一个0的index
first0 = i;
} else if (first0 >= 0) { //第一个0已找到,且找到第一个0后面第一个非0元素
swap(nums[first0], nums[i]); //把第一个0换成非0元素
i = first0; //从刚才第一个0后面重新找新的第一个0
first0 = -1;
}
}
};
解法2:双指针,j记录非0元素应该在的index,i去找非0元素;存在自我交换的重复操作
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int len = nums.size();
int j = 0; //遇非0元素自加
for (int i = 0; i < len; ++i)
if (nums[i])
swap(nums[j++], nums[i]); //把非0元素全部换到前面
}
};
解法3:解法2的优化,避免自己与自己交换值
//如果元素不为0,i,j跟着一起动。如果元素为零,j记录为零的下标
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int len = nums.size();
int j = 0;
for (int i = 0; i < len; ++i)
if (nums[i]) {
if (i > j) {
nums[j] = nums[i];
nums[i] = 0;
}
++j;
}
}
};