携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情
一、题目描述:
1089. 复写零 - 力扣(LeetCode) (leetcode-cn.com)
给你一个长度固定的整数数组 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
二、思路分析:
- 从左右两侧开始用双指针记录,左边每碰到一个0,后边就舍弃一个元素。一直到左边指针大于右边指针的时候,我们才停止检测有多少个0需要被复制。即i > j。
- 在左右两边指针相等时,即i==j时,需要做特殊判断。i记录的是当前元素,j记录的是下一个被舍弃的元素。那么如果当前元素是0,那么同时该元素是要被舍去的元素时,直接将其放到数组的最后面,相当于将这个0同时复制了也舍弃了。
- i: 用于从左边遍历元素,如果碰到0时则需要将j减去1表示舍弃一个元素为复制0腾出空间。
- j:用于从数组尾部开始,即右边,指向下一个即将被抛弃的元素。
- k:用于从后往前复制需要保留的元素时,指向下一个被复制元素需要去的位置。
三、AC 代码:
class Solution {
public void duplicateZeros(int[] arr) {
int len = arr.length;
int i = 0, j = len - 1;
while (i < j) {
//指针i如果遇到0需要将j减去1表示舍弃一个元素为0腾出位置
if (arr[i] == 0) {
j--;
}
i++;
}
int k = len - 1;
if (i == j && arr[i] == 0) {
arr[k--] = arr[j--];
}
while (j >= 0) {
if (arr[j] == 0) {
arr[k--] = 0;
}
arr[k--] = arr[j--];
}
}
}