算法讲解--复写零
一,题目描述
二,算法讲解
本题要求对数组进行就地修改,在有零的位置前插入一个零,其他数据直接不变,最后的数组大小和原数组一致。如上述用例。
法一:双指针法
使用两个指针分别控制开始复写的位置,和需要复写到达的位置。这时就要考虑若从数组开头开始则会导致数据覆盖,找不到后面的数据。因此从数组末尾开始复写。找到复写的位置之后,就需要找从哪一个数据开始,将该数据的值复写到最后位置。如实例一:
d指向最后的位置,c指向4的位置。通过循环将c位置的值依次给d位置,如果是0,c给一次之后,d自己再前面位置复写一个0。刚好c和d共同结束。复写完毕。那么如何确定c和d的位置?
可以通过如下方法:
首先c指向第一个元素的位置,d指向第一个位置的前一个位置。如图:
之后c每走一个非零元素,d加加操作,c走零元素,d加2操作。之后d走到数据末尾如上图。
特殊情况:d进行加等2操作时,会有可能越界的情况,所有需要特殊处理。如下例子:
经过上述处理如下图:
这是会发现出界了,为此需要特殊处理。c减减操作,d减减,且在该位置赋零。
总结一下:
1,先判断c的值
2,根据c的值确定d是走一步还是两步
3,确定d是否走到数组末尾
4,c再进行加加操作
5,全部结束后判断特殊情况进行特殊输出
找到c和d的位置之后,就可以从数组后向前复写,直到数组开头,复写结束。
代码实现:
void duplicateZeros(vector<int>& arr) {int c = 0;int d = -1;int size = arr.size()-1;for(c;d < size;c++){if(arr[c] == 0){d = d+2;}else{d = d+1;}if(d >= size){break;}} if(d == size+1){arr[d-1] = 0;d = d-2;c--;} while(c >=0){arr[d] = arr[c];if(arr[c] == 0){arr[d-1] = 0;d = d-1;}d--;c--;}}
法二:vector库法
由题意可以看到就是在数据0的位置前插入0,且数据总数不变从前向后切割。就可以用到两个函数第一个insert插入函数,resize函数实现剪切。代码实现如下:
void duplicateZeros(vector<int>& arr) {int dest = 0;int size = arr.size();for(dest;dest < arr.size();dest++){if(arr[dest] == 0){arr.insert(arr.begin()+dest,0);dest++;}}arr.resize(size);}
每次insert之后注意:都要进行加加操作。
三,练习
可以通过如下链接进行练习:
1089. 复写零 - 力扣(LeetCode)