数组专题:Leetcode283.移动零

107 阅读2分钟

原题链接:283. 移动零 - 力扣(Leetcode)

1.题意解析

题目特别强调了要原地操作。这就说明本地不能开辟新数组来辅助解题。

如果排除这个条件的话,按照一般的思维,就是开辟一个新数组,对原数组进行遍历,找到非零元素,赋值到新数组中,遍历完后就在新数组后补零。 现在就是要考虑,如何将这些操作压缩在同一个数组中完成。

2.解法一

按照上面的思路,我们可以定义两个指针:firstsecond

  • first:first指针用于遍历数组,找出非0元素。
  • secod:将找到的非零元素,赋值到second指针处,之后second指针前进一位。

遍历完之后,second指针前一位就指向了最后一个非0元素。此时从second指针开始,所有位置补0。

具体代码如下:

    public void moveZeroes(int[] nums) {
        int second = 0;
        for (int first = 0; first < nums.length; first++) {
            if (nums[first] != 0) {
                nums[second++] = nums[first];
            }
        }
        
        for (int i = second; i < nums.length; i++) {
            nums[i] = 0;
        }
    }

3.解法二

上面的解法被拆成了两部分,先是将非0元素挪到数组前面,再在其后面补0。 但我们可以换种思路: 同样是定义两个指针:firstsecond

  • first:first指针同样是找出非0元素。
  • second:second指针表示当前非0元素要交换的位置。在找出非0元素后,将其和second指针的元素交换,交换后second指针前进一位。

这就相当于,每次找出非0元素,就把它放到数组前面位置。随着first指针的遍历,最终所有非0元素都放在数组前面,后面一定全是0。

具体代码如下:

    public void moveZeroes(int[] nums) {
        int second = 0;
        for (int first = 0; first < nums.length; first++) {
            if (nums[first] != 0) {
                // 交换first指针元素和second指针元素的位置
                int temp = nums[first];
                nums[first] = nums[second];
                nums[second] = temp;
                // second前移1位,表示下一个非0元素要放的位置
                second++;
            }
        }
    }

4.总结

两种解法都用到了双指针,差别在于second指针所代表的含义。通常遇到原地操作的数组题目,一般用双指针都能解出来。