双指针算法(2)——复写零
双指针算法
定义两个指针,让后面的指针在数组中遍历,前面的指针先不动,符合题目要求时,让两个指针的数据进行交互,直到后面的指针走到数组结尾。
题目:
这个题,如果我们用两个数组下标去标记,一个遍历,一个交互(赋值),就会造成下面的结果
第一次复写时,发现数据已经被覆盖掉了,所以不可取。
其实,从前向后不行,从后向前可以,我们通过结果直到,数组的最后一个是4.
先让dest指向n-1。cur指向最后一个复写的数(4),然后判断,如果cur的值不为0,那么dest=cur,cur--,dest--;如果等于0,dest=0,dest-1=0,然后cur--,dest--。直到cur走到数组最开始。
现在问题就来到了,我们怎么找到哪个是复写的最后一个数?
这次我们就需要从前向后遍历了
cur指向0位置,dest指向-1.判断cur,不为0,dest++,如果dest++后不是在结尾,则cur++;为0,dest+=2,如果dest++后不是在结尾,则cur++。直到dest走到数组最后一个数字,此时cur就是复写的最后一个数。
但也有特殊情况比如:[1,0,2,3,0,4]。
我们走着走着发现dest突然越界了。dest访问到了n。
解决方法:我们发现出现这种错误的cur最后指向的一定是0,所以我们先让n-1等于0,然后,dest-=2,cur--。
最终代码如下:
void Solution(vector <int>&arr)
{int cur=0; int dest=-1;int n=arr.size();//找到最后一个数while(cur<n){if(arr[cur]) dest++;else dest+=2;if(dest>=n-1) break;cur++;}//处理边界if(dest==n){arr[n-1]=0;cur--;dest-=2;}//从后向前复写while(cur>=0){if(arr[cur]) {arr[dest]=arr[cur];cur--;dest--;}else{arr[dest--]=0;arr[dest--]=0;cur--;}}
}