LeetCode Hot100(4/100)——283. 移动零

文章目录

一、题目描述

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

示例:

text 复制代码
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

🧠 要求:

  1. 必须在**原地(in-place)**进行操作;
  2. 尽量减少操作次数。

二、题意总结

就是让数组中非零元素保持顺序不变的前提下,把所有 0 挪到末尾。

即实现 "非零元素 ➜ 前面" + "0 元素 ➜ 后面"


三、常见解法分析


✅ 解法一:双指针法(最优方案)

核心思想:

  • 用一个指针 slow 记录下一个非零元素应该放的位置;
  • 另一个指针 fast 遍历数组。
  • nums[fast] != 0 时,把它移动到 slow 的位置。
  • 遍历结束后,slow 之前全是非零,slow 之后全部设为 0。

流程图

numsfast!=0
numsfast==0
开始
初始化 slow=0
for fast 从 0 到 n-1
交换 numsslow 和 numsfast
slow++
跳过 fast++
遍历结束
输出结果


例子演示

nums = [0,1,0,3,12] 为例:

步骤 fast slow nums 说明
初始 - 0 [0,1,0,3,12] 开始
1 0 0 [0,1,0,3,12] 0,跳过
2 1 0 → 1 [1,0,0,3,12] 交换 1 与 0
3 2 1 [1,0,0,3,12] 0,跳过
4 3 1 → 2 [1,3,0,0,12] 交换 3 与 0
5 4 2 → 3 [1,3,12,0,0] 交换 12 与 0

最终结果:[1,3,12,0,0]


Java 实现(推荐)

java 复制代码
public class Solution {
    public void moveZeroes(int[] nums) {
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != 0) {
                // 交换非零元素和当前位置 slow 的数
                int temp = nums[slow];
                nums[slow] = nums[fast];
                nums[fast] = temp;
                slow++;
            }
        }
    }
}

复杂度分析

项目 复杂度
时间复杂度 O(n):只遍历一次
空间复杂度 O(1):原地操作

解法二:记录位置法(非交换优化版本)

思路:

  • 用一个指针 pos 指示下一个要放非零元素的位置;
  • 一次遍历,将所有非 0 覆盖到前面;
  • 再将剩下的地方补 0。
java 复制代码
public class Solution {
    public void moveZeroes(int[] nums) {
        int pos = 0;
        for (int num : nums) {
            if (num != 0) {
                nums[pos++] = num;
            }
        }
        while (pos < nums.length) {
            nums[pos++] = 0;
        }
    }
}

🔸 优点:

  • 更"干净"的写法,无需每次 swap。
  • 缺点:比双指针交换多一次遍历,但仍是 O(n)。

🧮 多方法对比

解法 关键思路 时间复杂度 空间复杂度 是否原地 稳定性
双指针 swap 快慢指针交换位置 O(n) O(1)
覆盖法 一次赋值一次补零 O(n) O(1)
新数组 借助中间数组重建 O(n) O(n)

四、方法演化图(Mermaid)

暴力法:新数组重建
优化:记录非零位置
最终方案:双指针交换法 O(n)


总结

要点 说明
🎯 目标 把 0 全部移到末尾,非 0 保持顺序
💡 核心 快慢指针 + 交换 或 赋值法
🧮 时间复杂度 O(n)
🧩 空间复杂度 O(1)
✅ 最优解 双指针交换法
相关推荐
青山是哪个青山1 分钟前
LeetCode 188:买卖股票的最佳时机 IV
算法
Tisfy15 分钟前
LeetCode 3498.字符串的反转度:一次遍历
leetcode·字符串·题解·遍历
a1879272183121 分钟前
【算法】树(二):队列与祖先——BFS 骨架三配件、短路透传与合流
算法·leetcode·二叉树··bfs·算法讲解·树遍历
syagain_zsx1 小时前
算法基础篇 · 03 枚举(C++ 题解)
c++·算法·二进制·枚举
weixin_307779131 小时前
C++代码实现MATLAB中的ode23tb函数功能
开发语言·c++·算法·matlab
我是章汕呐2 小时前
地级市能源消耗量及消耗强度数据【2006-2023年】平衡面板
人工智能·经验分享·算法·回归
charliejohn2 小时前
计算机考研 408 数据结构 堆的插入与删除 堆排序
算法
老鱼说AI3 小时前
从点积到希尔伯特空间:向量内积的几何本质与大模型相似度度量
人工智能·深度学习·线性代数·算法·机器学习·数学建模
地平线开发者3 小时前
模型部署|如何解决算子约束
深度学习·算法·自动驾驶
Navigator_Z4 小时前
LeetCode //C - 1254. Number of Closed Islands
c语言·算法·leetcode