给你一个长度固定的整数数组 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 <= 10^4
0 <= arr[i] <= 9
题目解释
该操作相当于从左到右将非'0'的数写一遍,将'0'写两遍,而这前size(arr的元素个数)个元素就是所需结果了,但是,不允许另外开空间。
算法思想
首先,我们考虑另外开空间的方法。
cur->遍历原数组
dest->新数组最后一个元素的下一个
从左到右依次向新数组写入数字,当数字个数与原数组相同时,终止循环
然后,我们考虑不开空间的方法。
第一步:找到最后一个需覆写的数。
目标:cur->最后一个要覆写的数,dest->最后一个数
int cur=0,dest=-1;
int arr_size=arr.size();//要用int,不能用size_t,不然和整型比较会有坑!
//目标:cur->最后一个要复写的元素
// dest->数组中最后一个元素
while(cur<arr_size)//用cur遍历数组
{
if(arr[cur]==0) dest+=2;//cur为0,填充两个
else dest++; //cur不为0,填充一个
if(dest>=arr_size-1) break;//cur以及cur以前的数足以填满数组,退出循环
cur++;//没填满,接着遍历
}
if(dest==arr_size)//特殊情况:[1,0]->[1,0],最后一个要覆写的元素为0时,可能让dest越界,特殊处理
{
arr[arr_size-1]=0;
cur--;dest-=2;
}
代码实现
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
int cur=0,dest=-1;
int arr_size=arr.size();//要用int,不能用size_t,不然和整型比较会有坑!
//目标:cur->最后一个要复写的元素
// dest->数组中最后一个元素
while(cur<arr_size)//用cur遍历数组
{
if(arr[cur]==0) dest+=2;//cur为0,填充两个
else dest++; //cur不为0,填充一个
if(dest>=arr_size-1) break;//cur以及cur以前的数足以填满数组,退出循环
cur++;//没填满,接着遍历
}
if(dest==arr_size)//特殊情况:[1,0]->[1,0],最后一个要覆写的元素为0时,可能让dest越界,特殊处理
{
arr[arr_size-1]=0;
cur--;dest-=2;
}
while(cur>=0)//便利需覆写的数
{
if(arr[cur]==0)
{
arr[dest--]=0;
arr[dest--]=0;
cur--;
}
else arr[dest--]=arr[cur--];
}
}
};