【LC100】No283. 移动零

题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

提示:

  • 1 <= nums.length <= 104

  • -231 <= nums[i] <= 231 - 1

进阶:

你能尽量减少完成的操作次数吗?

示例

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

链接

https://leetcode.cn/problems/move-zeroes/description/?envType=study-plan-v2&envId=top-100-liked

思路

abandon!

数组开头的一些特殊情况,有时候可以不用单独拿出来判断,融进循环里,无非是多交换几次的消耗。

第一次做题时的心路历程如下:

https://tiamo495.com/archives/lc75-no283.-yi-dong-ling

解法一:两次遍历,一次移动,一次补0

核心思路:把所有不是 0 的元素移动到前面来。

i 用来遍历,j 用来标识从左边数第一个 0 的位置。

代码

class Solution {
    public void moveZeroes(int[] nums) {
        if (nums == null) return;
        int j = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                nums[j] = nums[i];
                j++;
            }
        }
        for (; j < nums.length; j++) {
            nums[j] = 0;
        }
    }
}
  • 时间复杂度:O(n)

  • 空间复杂度:O(1)

解法二:一次遍历,快指针遍历,慢指针处理特殊

核心思路:当数组开头是连续非 0 元素时,快慢指针一起向右移动。

  • 慢指针找到左边开始数的第一个 0:快指针处理时,慢指针也处理,仅在处理完成后向右移动。

  • 快指针找到 0 之后的第一个非 0:当非 0 时才处理交换,遇到 0 直接跳过继续向右移动。

代码

class Solution {
    public void moveZeroes(int[] nums) {
        if (nums == null || nums.length == 1) return;
        int left = 0, right = 0;
        while (right < nums.length) {
            if (nums[right] != 0) {
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
            }
            right++;
        }
    }
}
  • 时间复杂度:O(n)

  • 空间复杂度:O(1)


【LC100】No283. 移动零
https://tiamo495.com//archives/lc100-no283.-yi-dong-ling
作者
tiamo495
发布于
2025年07月16日
许可协议