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。

流程图

nums[fast]!=0
nums[fast]==0
开始
初始化 slow=0
for fast 从 0 到 n-1
交换 nums[slow] 和 nums[fast]
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)
✅ 最优解 双指针交换法
相关推荐
草履虫建模12 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq14 小时前
分布式系统安全通信
开发语言·c++·算法
Jasmine_llq14 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
爱吃rabbit的mq15 小时前
第09章:随机森林:集成学习的威力
算法·随机森林·集成学习
(❁´◡`❁)Jimmy(❁´◡`❁)15 小时前
Exgcd 学习笔记
笔记·学习·算法
YYuCChi16 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
不能隔夜的咖喱16 小时前
牛客网刷题(2)
java·开发语言·算法
VT.馒头16 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
进击的小头16 小时前
实战案例:51单片机低功耗场景下的简易滤波实现
c语言·单片机·算法·51单片机
咖丨喱18 小时前
IP校验和算法解析与实现
网络·tcp/ip·算法