283. 移动零
!abstract 一句话本质 快慢指针分区,把数组分成"非零区 | 零区",不是排序而是划分。
!quote 链接
题目
给定数组 nums,将所有 0 移到末尾,保持非零元素相对顺序,原地修改。
思路(从暴力到最优)
暴力想法:开新数组,先装非零元素,再补零。时间 O(n),但要额外空间 O(n),不符合"原地"要求。
优化到原地 :用快慢指针模拟"分区"操作。
- fast:遍历者,负责"发现"非零元素
- slow:守门员,指向"下一个非零元素该放的位置"
每次 fast 发现非零元素,就交换到 slow 位置,然后 slow 前移。这样:
[0, slow)区间:已处理的非零区[slow, fast)区间:零区(被交换过来的)[fast, n)区间:待处理区
这和快速排序的 partition 思想一样,只是划分条件换成"是否为0"。
两种实现方式:
- 交换法:发现非零 → 交换到 slow → slow++(一步到位,0 自然沉底)
- 覆盖+补零法 :发现非零 → 覆盖到 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 思想关联仍未主动提