图解题库 / 快慢指针

283. 移动零

简单 含交互动画

学完这道你应该能: 说清它为什么用「快慢指针」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

原地把数组里所有 0 移到末尾,非零元素保持原来顺序

nums = [0, 1, 0, 3, 12]
输出 = [1, 3, 12, 0, 0]

思路解析

每遇到一个 0 就把后面元素整体前移,最坏要移 n² 次。换个思路:让非零元素一个个「向前归位」,0 自然就留在后面了。

fast 一路向前找非零;每找到一个,就和 slow 位置交换,slow 前进一格。因为 fast 是从左到右按原顺序遇到非零的,依次写入 slow,相对顺序天然不变;slow 左边永远是「已归位的非零」,最后空出来的位置自然是 0。

slow=0, fast=0:fast 当前是 0,不处理,fast 往前走,slow 停在 0 等一个非零。

fast=1 · 遇 1:fast 找到非零 1,和 slow(0号位)交换。1 归位到最前,slow 前进到 1。

fast=2 · 遇 0:fast 是 0,跳过。slow 停在 1 号位等下一个非零。

fast=3 · 遇 3:fast 找到 3,和 slow(1号位)交换:3 归位,slow 前进到 2。

fast=4 · 遇 12:fast 找到 12,和 slow(2号位)交换:12 归位,slow 前进到 3。

完成:fast 走完,slow 左边 [1,3,12] 全是归位的非零,后面自然剩下两个 0:[1,3,12,0,0]

slow 是「写指针」、fast 是「读指针」——读到合格的就写到 slow 并前进。删除元素、去重都是这套快慢指针。

参考代码(Python)

Python
1slow = 0
2for fast in range(len(nums)):
3    if nums[fast] != 0:                       # 找到非零
4        nums[slow], nums[fast] = nums[fast], nums[slow]
5        slow += 1                             # 归位一个

复杂度分析

  • 时间复杂度:O(n) —— fast 扫一遍
  • 空间复杂度:O(1) —— 原地交换

套路模板

记住骨架:fast 读、slow 写、合格才写并进位。删除有序数组重复项、移除元素都是改一下「保留」条件。

Python
1# 「原地保留/移动符合条件的元素」都套
2slow = 0                          # 写指针
3for fast in range(n):             # 读指针
4    if 保留(nums[fast]):          # 合格就写入
5        nums[slow] = nums[fast]; slow += 1
6# slow 左边就是结果,长度 = slow

易错点

  • 直接把非零覆盖、不管 0 → ✅ 用交换或最后补 0(覆盖会丢掉本该留到末尾的 0)
  • slow 每轮都 +1 → ✅ 只有写入时才 slow += 1(slow 只在放入合格元素后前进)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →35. 搜索插入位置 ← 返回题库