lettcode 1089. 复写零

lettcode 1089. 复写零_第1张图片代码:

class Solution {
    public void duplicateZeros(int[] arr) {
        int cur = 0, dest = -1, n = arr.length;
        // 1. 先找到最后⼀个需要复写的数
        while (cur < n) {
            if (arr[cur] == 0) dest += 2;
            else dest += 1;
            if (dest >= n - 1) break;
            cur++;
        }
        // 2. 处理⼀下边界情况
        if (dest == n) {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        // 3. 从后向前完成复写操作
        while (cur >= 0) {
            if (arr[cur] != 0) arr[dest--] = arr[cur--];
            else {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }
}

题解:

        我们可以定义两个指针,一个指针 cur 用来遍历数组,另一个指针 dest 用来复写元素到数组中

        对于示例 1 如果我们采用从左到右的方式来复写元素:

       cur     cur

        1        0        2        3        0        4        5        0

        1        0        0

      dest    dest

        当 cur 指向 1 时,将 dest 指向的位置设为 1,然后 cur 和 dest 都向右移,当 cur 指向 0 时,将 dest 指向的位置和下一个位置都设为 0 ,此时我们就会发现问题,源数组中的 2 还没有写就被覆盖了

        所以采取从左到右的方式是错误的,我们应该使用从右到左的方式

                                               cur     cur

        1        0        2        3        0        4        5        0

                                                          0        0         4

                                                        dest    dest    dest

        让 cur 指向最后一个复写的数,从右到左依次遍历复写,这样就不会出现覆盖的情况


        那么现在我们面临的问题就是如何让 cur 去指向最后一个复写的数

        我们采用以下的逻辑,模拟复写的过程,让 cur == 0,dest == -1,当 cur 指向的数不为 0 时,dest 就 ++,当cur 指向的数为 0 时 dest  就+= 2,直到 dest >= arr.length - 1 为止

               cur     cur                                   cur

                1        0        2        3        0        4        5        0

   dest    dest                                                                dest

        我们通过上述流程便能让 cur 指向最后一个复写的数,并且 dest 刚好在数组的末尾,可以直接根据当前的位置进行从右到左的复写


        我们要是只考虑上述的情况写出来的代码是有 bug 的

        比如现在有一个例子:        1.0.2.0.3.0.5.0

        我们正确复写的结果应该是 1,0,0.2.0.0.3.0

        但通过我们上述的方法进行分析:

                                                 cur     cur

          1        0        2        0        3        0        5        0

          1        0        0        2        0        0        3        0        0

                                                                     dest            dest

        我们发现,当最后一个复写的数为 0 时,采用从右到左的方式复写可能会多出一个 0 

        所以我们要对这种特殊情况进行判断,当查找最后一个复写的数时 dest == arr.length ,就说明此时最后一个复写的数为 0,并且最终结果会多次一个 0 ,我们需要对特殊情况进行处理,将

arr[arr.length-1] = 0,cur-- ,dest -= 2

你可能感兴趣的:(leetcode,java,算法,leetcode)