给你一个长度固定的整数数组 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]
提示:
1 <= arr.length <= 104
0 <= arr[i] <= 9
用下标充当指针
从后往前写入数据,因为从前往后写入数据会覆盖未判断的数据
1 找到最后一个要被写入的数据:
cur=0(遍历数组),dest=-1 (占位),初始化为-1表示还未占位
a 如果cur指向的数据是非0元素,dest++,占1个位置
b 如果cur指向的数据是0,dest+=2,占两个位置
c 每一次都要判断dest是否>=n-1,dest==n-1表示占位已经满了,dest==n是因为当最后一个写入的数据是0,要复写两次,且dest此时指向是n-1的位置,dest再占一个位置,那就越界了
一旦占位已满或者dest越界,就结束循环,此时cur指向的是要被写入的最后一个数据
2 处理边界情况:dest==n,被写入的最后一个元素是0且位置不够,发生越界,只能写入一次
让arr[n-1]=0,处理完成后,cur--,指向下一个要写入的数据(该写入几次就写入几次)
dest-=2,指向下一个要写入数据的位置
3 正常写入数据
非0写入一次,0写入两次
class Solution
{
public:
void duplicateZeros(vector& arr)
{
int cur = 0;//遍历数组,找到最后一个要被写入的数字
int dest = -1;//为被写入的数字模拟占位
int n = arr.size();
while(cur=n-1)//位置已经满了,已经找到最后一个要被写入的数字
{
break;
}
cur++;
}
if(dest==n)//当最后一个要被写入的数据是0时,0要复写两次,但是dest已经越界了
{
arr[n-1] = 0;//越界的位置不用写0了,在没有越界的位置写入一个0
cur--;//指向下一个要写入的数据
dest-=2;//指向下一个要写入数据的位置
}
while(cur>=0)//写入数据
{
if(arr[cur])//非0,写入1次
{
arr[dest--] = arr[cur--];
}
else//0,写入两次
{
arr[dest--] = 0;
arr[dest--] = 0;
cur--;
}
}
}
};