持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情
题目描述
给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。
注意:请不要在超过该数组长度的位置写入元素。
要求:请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。
示例 1:
输入:[1,0,2,3,0,4,5,0]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]
示例 2:
输入:[1,2,3]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,2,3]
提示:
- 1 <= arr.length <= 10000
- 0 <= arr[i] <= 9
思路
今天的题目一看挺简单的,如果允许我们新开一个数组并返回,我们直接按照题意从前到后处理即可。原地处理带来的一个问题是,如果顺序处理,后面还没被遍历到的数字就会被覆盖。所以,我们必须从后往前处理。那么新的问题就是,从后往前遍历,如何知道原位置为i的数字会被移动到什么地方。由于每个0都会被复写,所以i级之前有zeroCount个0,那么i的新位置就是i + zeroCount。另外,如果遇到0,由于复写,不只是移动它本身,还要吧i + zeroCount - 1位置置为0。
所以,我们的方法是先遍历一遍数组总共有多少个0,其实就是最后1位及之前0的个数。然后从后往前遍历,移动数的同时,注意遇到0,就执行zeroCount--,这样zeroCount在遍历到i的时候,就是代表i及之前有多少个0。
上述方法有一个注意点,在给arr数组的某个位置赋值的时候,要判断一下是否越界。理论上,只要存在0,总会有数字被移到数组外面去。
Java版本代码
class Solution {
public void duplicateZeros(int[] arr) {
// 统计出0的个数
int zeroCount = 0;
for (int num : arr) {
if (num == 0) {
zeroCount++;
}
}
int len = arr.length;
// 如果i及之前,0的个数为zeroCount,则i的位置需要移动到i + zeroCount
// 注意:给arr[k]赋值的时候,注意k的大小,不要越界;理论上,只要存在0,总会有数字被移到数组外面去
for (int i = len - 1; i >= 0; i--) {
if (i + zeroCount < len) {
arr[i + zeroCount] = arr[i];
}
if (arr[i] == 0) {
// 因为复写0,如果遇到0,那么除了移动 i 到 i + zeroCount,还需要在前面补一个0
if (i + zeroCount - 1 < len) {
arr[i + zeroCount - 1] = 0;
}
zeroCount--;
}
}
}
}