刷题日记 1089. 复写零

86 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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

二、思路分析:

  1. 从左右两侧开始用双指针记录,左边每碰到一个0,后边就舍弃一个元素。一直到左边指针大于右边指针的时候,我们才停止检测有多少个0需要被复制。即i > j。
  2. 在左右两边指针相等时,即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--];
        }
    }
}