1.题目链接:1089.复写零
2.题目描述:
给你一个长度固定的整数数组 arr
,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。
注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。
示例 1:
输入:arr = [1,0,2,3,0,4,5,0] 输出:[1,0,0,2,3,0,0,4] 解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]
示例 2:
输入:arr = [1,2,3] 输出:[1,2,3] 解释:调用函数后,输入的数组将被修改为:[1,2,3]
3.解法(原地复写 - 双指针)
算法思路:
如果从前向后进行原地复写操作的话,会导致没有复写的数被覆盖掉。因此我们选择从后往前的复写策略。
但是从后往前复写的时候,我们需要找到最后一个复写的数,因此我们的大题流程分两步:
- 从前向后,寻找最后一个复写的数
- 从后向前,进行复写操作
算法流程:
- 初始化两个指针:cur = 0,dest = -1
- 找到最后一个复写的数: 当cur < n的时候,一直执行下面的循环: 判断cur的元素,如果cur的元素为0,则dest += 2;如果cur的元素不为0,则dest++。 判断dest是否>=n-1,如果dest>=n-1则break跳出循环,此时cur找到最后一个复写的数;反之dest<n-1,则cur++;
- 判断dest是否越界: 如果dest == n,则dest越界。令n-1位置为0,dest -= 2,cur--; 如果dest == n-1,则无需有任何操作。
- 从后向前,进行复写:判断cur位置的值 a.如果cur位置的值为0,则dest,dest--的位置修改成0,dest -= 2; b.如果cur位置的值不为0,则dest位置修改成cur位置的值,dest-- ; c.cur--。继续复写下一个数
4.C++算法代码
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
int cur = 0, dest = -1,n = arr.size();
while(cur<n)
{
if(arr[cur] == 0)
{
dest += 2;
}
else
{
dest++;
}
if(dest >= n-1)
break;
cur++;
}
if(dest == n)
{
arr[n-1] = 0;
dest -= 2;
cur--;
}
while(cur>=0)
{
if(arr[cur] != 0)
{
arr[dest] = arr[cur];
dest--;
}
else
{
arr[dest] = arr[dest-1] = 0;
dest-=2;
}
cur--;
}
}
};