283. 移动零

简单 含交互动画

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

AI 私教 · 就着本题动画讲
卡住了不用硬扛,按 8 步把这题真正走通。
从读题、试解、找法到手写代码,边问边打勾,适合第一次系统学算法的同学。

题目描述

原地把数组里所有 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 · 遇 0:负例分支:fast 当前是 0,不处理,slow 留在原地,只让 fast 往前走。slow 在等下一个非零来填它这个空位。

fast=1 · 找到非零 1:fast 找到非零 1。该把它和 slow(0号位)交换,让 1 归位到最前。

fast=1 · 交换 → slow 进位:1 和 0 交换,数组变 [1,0,0,3,12],1 归位到最前。因为放入了一个数,slow 才前进到 1

fast=2 · 又遇 0:又一次负例:fast 是 0,跳过,slow 仍停在 1 号位等下一个非零。看出节奏了吗——slow 只在「放数」时才动。

fast=3 · 找到 3:fast 找到非零 3,准备和 slow(1号位)交换。

fast=3 · 交换 → slow 进位:3 和 1 号位的 0 交换,数组变 [1,3,0,0,12],3 归位。slow 前进到 2。前面已经是 [1,3] 了。

fast=4 · 找到 12:fast 走到最后,找到非零 12,准备和 slow(2号位)交换。

fast=4 · 交换 → 完成:12 和 2 号位的 0 交换,数组变 [1,3,12,0,0]。slow 左边 [1,3,12] 全是按原序归位的非零,后面自然剩两个 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 扫一遍,slow 只增不减,指针只走一遍
  • 空间复杂度: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

易错点

  • 错误写法:直接 nums[slow]=nums[fast] 覆盖、不管 0正确写法:用交换 swap(或先压缩非零、最后补 0)(覆盖会把本该留到末尾的 0 直接抹掉,得到的数组里 0 的个数都对不上;交换才同时保住顺序和那些 0)
  • 错误写法:slow 每轮都 +1正确写法:只有写入(交换)时才 slow += 1(slow 只在放入合格元素后前进,遇 0 时不动,否则归位位置会错乱)

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

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