题目链接:
https://leetcode.cn/problems/move-zeroes/
题目描述:
给定一个数组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:遇到 0 移动后,i 不能 ++!
你现在代码:
for(int i=0;i<nums.size();i++){ if(nums[i]==0) { memmove(...); // 把0删掉 } }错在哪?比如数组:[0,1,0]
- i=0,发现是 0 → 删掉 → 数组变成
[1,0] - 然后i 变成 1
- 直接跳过了新的 i=0 位置的 1
结果:会漏检查元素!
所以删掉 0 之后 i 不动,不 ++!
错误 2:不是已经在覆盖0的时候个数不是已经变少了吗,那为什么还要pop
memmove 只是把数据往前挪,不会改变 vector 的大小!vector 大小不会自己变少!
我以为:
memmove(&nums[i], &nums[i+1], 长度);执行完 →数组长度自动 -1
错!大错特错!
memmove 只负责拷贝内存,不负责修改 vector 大小!
举个超级直观的例子:数组[0,1,2]size = 3
执行:
memmove(&nums[0], &nums[1], 2*sizeof(int));数组变成:
[1,2,2]size 还是 3!没变!最后那个2还在!0 被覆盖了,但数组长度没变短!
所以必须 pop_back ()
因为:
- memmove 往前挪了数据
- 但最后多出来的一个元素还在
- vector 长度依旧不变
class Solution { public: void moveZeroes(vector<int>& nums) { //计算0的个数 int len=0; int i=0; while(i<nums.size()){ if(nums[i]==0) { len++; //将0覆盖掉 memmove(&nums[i],&nums[i+1],sizeof(int)*(nums.size()-i-1)); //要将数组个数减1 nums.pop_back(); } else{ i++; } } //然后末尾再将对应0的个数补齐 for(int i=0;i<len;i++){ nums.push_back(0); } } };