力扣HOT100-4 移动零(Java实现)

题目

题目解读

1.只能原地对数组进行操作,保持非零元素的原有顺序

2.就是把零移动到末尾

开始解题

一、覆盖 + 补零

思路:

想象我们有一个"慢指针" slow,它始终指向"下一个非零元素应该填入的位置"。

另一个"快指针" fast 遍历整个数组:

如果 nums[fast] 不是 0,就把它覆盖到 slow 的位置,然后 slow 右移一位。

如果 nums[fast]0,就跳过。

遍历结束后,slow 左边的所有位置都是非零元素,且相对顺序不变。此时 slow 及其之后的位置都应该变成 0,只需用另一个循环填充即可。

核心流程:

1.初始化 slow = 0。

2.用 fast 遍历数组:

如果 numsfast != 0:执行 numsslow = numsfast,slow++。

3.遍历完成后,用 for (i = slow; i < nums.length; i++) 将剩余位置全部置为 0。

代码

java 复制代码
public void moveZeroes(int[] nums) {
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != 0) {
                nums[slow] = nums[fast];
                slow++;
            }
        }
        // 将 slow 到末尾全部填 0
        for (int i = slow; i < nums.length; i++) {
            nums[i] = 0;
        }
    }

二、交换法

思路:

方法一在覆盖时,fast 位置的原值被残留下来,最后需要额外补零。

我们可以改用交换 的思路:当 fast 遇到非零元素时,让它与 slow 位置的元素交换。

由于 slow 位置上的元素要么是 0,要么就是已经被处理过的非零元素 (如果数组前面没有 0,slowfast 会同步前进,交换不会产生负面影响)。

这样,零会被一步步"推"到数组末尾,无需最后的补零循环,每个元素至多参与一次交换,操作次数更少。

核心流程:

1.初始化 slow = 0。

2.用 fast 遍历数组:

如果 numsfast != 0:

交换 numsslow 和 numsfast

slow++。

3.遍历结束后,数组已经满足要求,无需额外操作。

代码

java 复制代码
public void moveZeroes(int[] nums) {
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != 0) {
                // 交换 nums[slow] 和 nums[fast]
                int temp = nums[slow];
                nums[slow] = nums[fast];
                nums[fast] = temp;
                slow++;
            }
        }
    }

感谢您能够看到这里,一起见证小何同学的算法学习,如果您有不同的见解,希望能得到您的指点和点悟;如果您是和我一样的同学,也希望这篇文章能对您有所帮助。