给定一个固定长度的整数数组
arr
,每次出现0时,将剩余的元素向右移动,超过原始数组长度的元素不会被写入。
事例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
leetcode传送门: leetcode.com/problems/du…
解题
step1:先看看怎么移动数组中的元素
先用人的思维想一想怎么移动数组里的元素:有一个数组[1,2,3,4]
,从0开始往后移动,将下标为0的移动到下标为1的位置上,下标为1的移动到下标为2的位置上,依次类推。。。这样就完成数组的移动啦,最后我们可以得到这样的结果:[1,1,2,3]
,对吧,人的思维这样想起来好像一切都很完美,让我们把上面这段想法付诸实践,用程序写出来:
public class DuplicateZeros {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4};
int i = 0;
while (i < arr.length - 1){
arr[i+1] = arr[i];
i++;
}
System.out.println(Arrays.toString(arr));
}
}
output: [1, 1, 1, 1]
哎?好像输出的结果不对,为什么会这样呢?稍微有点编程基础的应该都知道,不过我还是来画个图解释一下吧~
原来是在程序执行的过程中前面的值把后面的覆盖掉了,emmmm,开动大脑好好想想,可不可以一开始就从元素值为3的位置移动呢(数组的capacity就只有4个,从最后一个下标往后移动,就没地方放了)?这样就可以避免前面的值覆盖后面的。
这次让我们先画图将意思表达出来,然后再来写程序吧~~
程序如下:
public class DuplicateZeros {
public static void main(String[] args) {
int[] arr = new int[]{1, 2, 3, 4};
int i = arr.length - 1;
while (i > 0) {
arr[i] = arr[i-1];
i--;
}
System.out.println(Arrays.toString(arr));
}
}
output:[1, 1, 2, 3]
step2: 大胆猜想一下解法
学会了怎么移动数组后就简单啦,下面说说我的思路:
- 算出数组中0的个数,数组中元素的长度 + 元素0的个数 = 要移动的步长
- 将步长参与计算,遇到0就多走一步
- 因为是固定数组,所以超出的部分丢弃掉
还是画图更能清楚的表达意思:
解题如下:
class Solution {
public void duplicateZeros(int[] arr) {
if (arr == null || arr.length == 0) return;
//计算数组中0的个数
int zeros = 0;
for (int num : arr) {
if (num == 0) {
zeros++;
}
}
if (zeros == 0) return;
int len = arr.length;
//计算数组的capacity和要走的步长
int i = len - 1, j = i + zeros;
while (i != j) {
insert(arr, i, j--);
if (arr[i] == 0) {
//遇到0多走一步
insert(arr, i, j--);
}
i--;
}
}
private void insert(int[] arr, int i, int j) {
//被丢弃的部分不参与运算
if (j < arr.length) {
arr[j] = arr[i];
}
}
}
step3: 证实猜想
果然印证了我们的想法,成功啦~~