题源(力扣平台)

解题原理:
先考虑"异地拷贝数组",进行复写操作。然后考虑从左往右进行原地复写,但是发现这个过程中会覆盖掉未处理却应该处理的数据。于是考虑从右往左进行复写,则分为两步:
1.找到最后一个需要复写的数字
2.从后往前进行复写
cpp
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
//1、找最后一个需要复写的数字---数组下标
int des = -1 , cur = 0, n = arr.size();
while(cur < n ){
if(arr[cur] != 0) des+=1;
else des+=2;
if(des >= n - 1) break;
cur++;
}
//我的错解:
//while(des < n ){
// if(arr[cur] != 0) des+=1;
// else des+=2;
// cur++;
//}
cout << cur;
//2.从后向前进行复写
//结束条件:cur < 0
if(des == n){
arr[n-1] = 0;
des-=2;cur--;
}
while(cur>=0 && des >= 0){
if(arr[cur] == 0){
arr[des] = arr[des - 1] = 0;
des-=2;
}
else {
arr[des] = arr[cur];
des--;
}
cur--;
}
// for(int des = -1,cur = 0;des < arr.size();cur++){
// if(arr[cur] != 0) des++;
// else des+=2;
// cout << des;
// }
}
};
我的出错点:
1.在找最后一个需要复写的元素下标时,没有搞清楚循环结束情况,写成了des > n时结束循环。
这是因为对"双指针算法"的错误理解与思路的不清晰:des是因为cur才有变化的,所以循环主体判断条件应该是cur,而不是des,本末倒置了;des在>n时确实是需要考虑到的边界情况,但是并没有考虑清楚des在越界时的真正含义
2.没考虑到特殊边界情况(最后一个复写元素为0时),以及处理方式不对
由1.能考虑到des>=n-1时,就应该有两种情况。des = n -1;des = n;
而对应的复写操作中,访问了arr[des]此时就已经越界,就算考虑不到最后一个复写元素为0的情况,也应该考虑到数组访问的这种边界情况。
总结:
如何能在第一次写的时候就考虑全面?
deepseek给我的建议;
编写算法时的思维习惯
-
画图:用下标模拟每一步的变化。
-
考虑极端值:最小长度(1)、全零、零出现在不同位置。
-
关注索引变化:当增量可能为 2 时,一定要思考"刚好越界"的情况。