283. 移动零

283. 移动零

!abstract 一句话本质 快慢指针分区,把数组分成"非零区 | 零区",不是排序而是划分。
!quote 链接

题目

给定数组 nums,将所有 0 移到末尾,保持非零元素相对顺序,原地修改。

思路(从暴力到最优)

暴力想法:开新数组,先装非零元素,再补零。时间 O(n),但要额外空间 O(n),不符合"原地"要求。

优化到原地 :用快慢指针模拟"分区"操作。

  • fast:遍历者,负责"发现"非零元素
  • slow:守门员,指向"下一个非零元素该放的位置"

每次 fast 发现非零元素,就交换到 slow 位置,然后 slow 前移。这样:

  • [0, slow) 区间:已处理的非零区
  • [slow, fast) 区间:零区(被交换过来的)
  • [fast, n) 区间:待处理区

这和快速排序的 partition 思想一样,只是划分条件换成"是否为0"。

两种实现方式

  1. 交换法:发现非零 → 交换到 slow → slow++(一步到位,0 自然沉底)
  2. 覆盖+补零法 :发现非零 → 覆盖到 slow → slow++,最后把 [slow, n) 全填 0

交换法更直观,覆盖法写操作更少(但需两次遍历)。

关键卡点

!warning 我当时卡在这

  • 为什么需要两个指针?一个指针无法分区,必须有人"找非零"、有人"守位置"
  • 交换 vs 赋值?赋值会覆盖元素,必须两步(先填非零,后补零);交换一步到位
  • 边界优化:当 slow === fast 时,交换是多余的(自己换自己),可加判断跳过

代码

javascript 复制代码
var moveZeroes = function(nums) {
    let slow = 0;
    for (let fast = 0; fast < nums.length; fast++) {
        if (nums[fast]) {
            if (slow !== fast) {  // 优化:避免自己换自己
                [nums[slow], nums[fast]] = [nums[fast], nums[slow]];
            }
            slow++;
        }
    }
    // 题目要求原地修改,return 可省略
};

复杂度

  • 时间:O(n),一次遍历
  • 空间:O(1),只用了两个指针变量,原地修改

一句话记忆点

!tip 下次看到类似题 数组分区类问题 → 快慢指针,一个找元素,一个守位置。partition 思想可迁移。

相似题 / 套用模板

  • 删除元素类:27. 移除元素(把等于 val 的"删除"=移到末尾)
  • 分区类:75. 颜色分类(三指针分区)
  • 快排 partition:划分思想,条件换成"是否为0"

复习记录

2026-07-06 第 1 次复习

结果:通过 ✅(阶段 0→1)

记得牢:

  • 同向快慢指针(fast 找非零,slow 守位置),原地修改,无需额外数组
  • slow 的含义:下一个非零元素应该放的位置
  • 遇到 nums[fast] !== 0 就交换到 slow 位置,然后 slow++
  • 时间 O(n),空间 O(1)

需要加强:

  • [0] 这种单元素 0 的处理细节:fast 只遍历一次,不是"一直++"
  • 题解原代码里 slow === fast 的优化(避免自己换自己)本次回忆没提到,下次注意

2026-07-13 第 2 次复习

结果:通过 ✅(阶段 1→2)

记得牢:

  • 双指针思路清晰:s 守非零位置,f 找非零元素,交换
  • 时间 O(n),空间 O(1)
  • 边界分析到位:空数组、全零、无零三种情况都答对
  • 代码标准 AC,一步到位

需要加强:

  • partition 思想联系没提(这题本质是快排划分,条件换成"是否为0")
  • 三个区间 [0,slow) [slow,fast) [fast,n) 的不变量没说清
  • slow === fast 优化两次复习都没提到,下次务必记住

2026-08-04 第 3 次复习

结果:通过 ✅(按复习偏好,阶段 2 保持,下次复习延后 15 天至 2026-08-19)

记得牢:

  • 三区间不变量这次讲清了:[0,s) 已归位非零区、[s,f) 零区、[f,n) 未知区(第 2 次复习标记的薄弱点已克服 ✅)
  • 交换 vs 覆盖:覆盖会漏元素,还得删 f 位置 + 重新判断 + cnt 计数补零,交换一步到位
  • 边界三种都对:全非零 s/f 同步、全零 f 走到越界 s 不动、空数组不进循环
  • 1 分 53 秒 AC,代码标准

需要加强:

  • partition 思想联系(连续三次没提):本质是快排划分,条件换成"是否为 0",可迁移到 75 颜色分类、27 移除元素
  • slow === fast 优化(连续三次没提):slow===fast 时交换自己换自己是多余的,可加判断跳过。微优化不影响正确性,但笔记一直标记

2026-08-23 第 4 次复习

结果:毕业 🎓(阶段 2→3,下次防遗忘复习 2026-09-07)

记得牢:

  • 快慢指针代码一次 AC:s 守非零边界、f 扫描,交换非零到 s,O(n)/O(1)
  • 三区间不变量、交换 vs 覆盖区别仍清楚

需要加强:

  • slow === fast 优化(连续第 4 次没写):自己换自己可跳过,微优化不影响正确性
  • partition 思想关联仍未主动提
相关推荐
船厂电气自动化ai大模型2 小时前
AI大模型与数学·第57课 傅里叶全套工具链综合实战:串联级数/连续变换/DFT/FFT,图像、音频、扩散模型完整例题
数据结构·人工智能·深度学习·算法·机器学习
人工智能培训3 小时前
人工智能数据安全下的个人信息保护实践方案
大数据·人工智能·算法·生活
元启数宇4 小时前
幕墙AI设计算法逻辑:元启数宇如何智能分格
人工智能·算法
宵时待雨4 小时前
优选算法专题16:多源BFS
算法·宽度优先
重生之后端学习4 小时前
53. 最大子数组和[中等]✅
java·数据结构·算法·leetcode·职场和发展
INGNIGHT4 小时前
1908 · 布尔表达式求值(stack单调栈&dfs)
开发语言·c++·算法
lucas_AI5 小时前
把表格压成 64 个 token,长文档问答反而更准了:先找表,再看数
人工智能·深度学习·算法
Zzz 小生5 小时前
Lazy Theta*:把昂贵的视线检测留到“真正需要”时再做
人工智能·算法·贪心算法·推荐算法
l1258655 小时前
# LangGraph Deep Research Agent 全流程设计:多轮研究、人机协同与真实来源管理
数据库·人工智能·python·算法·自然语言处理·oracle·langchain