【Hot100-Java简单】/LeetCode 283. 移动零:两种 Java 高效解法详解

LeetCode 283 题 (Move Zeroes) 是一道经典的数组操作题。题目要求将数组中所有的 0 移动到末尾,同时保持非零元素的相对顺序,且必须原地 (In-place) 操作,不能使用额外的数组空间。

本文提供两种 时间复杂度的 Java 解法,分别对应"覆盖后填充"和"交换"两种核心思维。


方法一:覆盖 + 补零(推荐:逻辑最清晰)

核心思路

我们可以把数组 nums 想象成一个栈。维护一个指针 j,用来指向下一个存放非零元素的位置。

  1. 第一次遍历(归位):

    遍历整个数组,只要遇到 非零元素,就直接把它"写"到 numsj 的位置,然后 j 后移一位。

    • 注意:这里我们通过直接覆盖来移动数据,不用管被覆盖的数字,也不用管 0 去哪了。
  2. 第二次处理(补零):

    遍历结束后,j 之前的位置存储的都是按顺序排列好的非零数。那么,从 j 到数组末尾的所有位置,理应全是 0。直接批量赋值即可。

Java 代码实现

Java

复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int j = 0; // j 指向当前非零元素应该存放的位置

        // 1. 第一步:将所有非零元素移到数组开头
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                nums[j] = nums[i]; // 直接覆盖
                j++;
            }
        }

        // 2. 第二步:将剩余位置全部填充为 0
        // 使用 Arrays.fill 是 Java 中处理批量赋值最高效的方式
        Arrays.fill(nums, j, nums.length, 0);
    }
}

复杂度分析

  • 时间复杂度 :。我们需要遍历数组一次来移动非零数,Arrays.fill 底层虽然也是循环但极快,整体仍为线性时间。

  • 空间复杂度 :。只使用了几个整数变量。


方法二:双指针交换(进阶:一次遍历)

核心思路

方法一在逻辑上分成了"移数"和"补零"两步。方法二试图通过交换 (Swap),在一次遍历中完成所有任务。

维护一个指针 j,它的含义是:当前最左边的 0 的位置(或者说是等待被非零元素交换的位置)。

  1. 用指针 i 遍历数组。

  2. 当 nums[i] 是 非零数 时:

    • 将其与 nums[j] 进行交换。

    • 交换后,非零数归位到了左边,原来的 0 被换到了当前位置。

    • j 向后移动一位,准备接收下一个非零数。

  3. 当 nums[i] 是 0 时:

    • i 继续走,j 停在原地(标记这里有个 0 等待被换走)。

这种方法形象地被称为"滚雪球":j 和 i 中间的区域就是积累的 0,我们不断把后面的非零数扔到雪球前面去。

Java 代码实现

Java

复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int j = 0; // j 指向第一个 0 的位置
        
        for (int i = 0; i < nums.length; i++) {
            // 只有遇到非零元素才执行操作
            if (nums[i] != 0) {
                // 优化:只有当 i > j 时才交换
                // (避免数组开头全是非零数时,自己和自己交换)
                if (i > j) {
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                }
                j++;
            }
        }
    }
}

复杂度分析

  • 时间复杂度 :。严格的一次遍历。

  • 空间复杂度 :。


总结:哪种方法更好?

特性 方法一 (覆盖+补零) 方法二 (双指针交换)
操作次数 总是 次写入 (移动 + 补零) 最少 0 次 (如果全是非零),最多 N 次
代码可读性 ⭐⭐⭐⭐⭐ (利用了 Java API) ⭐⭐⭐⭐ (交换逻辑稍显复杂)
推荐场景 通用推荐。逻辑分离,不易出错。 特殊优化。如果已知数组中 0 很少,或者写操作代价很高时使用。

对于 Java 选手,通常推荐使用 方法一 ,因为它利用了 Arrays.fill,代码更简洁,且在大多数测试用例下性能非常稳定。

相关推荐
Smoothcloud润云36 分钟前
PyTorch大模型权重加载与启动耗时优化实战:定位磁盘、内存与显存瓶颈
人工智能·pytorch·python·深度学习·gpu算力
databook44 分钟前
从循环到向量化:NumPy提速的7个关键思维
python·数据分析·numpy
棉猴1 小时前
玩游戏学Python1-Python和pgzero库的安装
python·pygame·玩游戏·pgzero·pgzrun
诺伦2 小时前
GEO优化数据实证:78%引用流向官网的机制拆解与小品牌三步管线实战教程 | RiseClaw玄策
python·seo·geo·内容营销·ai搜索
oooost2 小时前
pytorch学习笔记1
python·学习方法
数字融合2 小时前
透明化视频孪生虚实映射一体化融合技术
人工智能·python·数码相机
jack186893 小时前
Lovable.Dev 全栈应用快速落地实战指南
python
华研前沿标杆游学3 小时前
【标杆研学】走进茅台集团|对标学习长期主义与匠心精神
python
GitFun4 小时前
KDJ vs RSI:11年数据实测,金叉死叉输了48个点
python·股票·量化交易
李可以量化4 小时前
从零读懂配对交易(上):从套利本源到配对交易的核心逻辑
python·区块链·量化交易·通达信·qmt