图解题库 / 三指针

75. 颜色分类

中等 含交互动画

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

题目描述

原地把只含 0、1、2 的数组排成 0 在前、1 在中、2 在后。

nums = [2, 0, 2, 1, 0]
输出 = [0, 0, 1, 2, 2]

思路解析

l 左边都是 0,r 右边都是 2,i 是当前位置。i 遇 0 就和 l 换,l 和 i 都前进;遇 2 就和 r 换,r 后退,但 i 不动,因为换过来的数还得再看;遇 1 就 i 直接前进。

三指针就位:三个指针就位:l 和 i 都从最左边开始,r 在最右边。i 负责逐个检查,l 和 r 负责把 0 和 2 归位。

i=0 看到 2:当前是 2,和 r(下标 4)交换,r 退到 3。注意 i 不前进——因为换过来的 0 还没检查。

i=0 看到 0:换过来是 0,和 l(下标 0)交换,l 和 i 都前进到 1。

i=1 看到 0:又是 0,和 l(下标 1)交换,l 和 i 都前进到 2。左边已经是 [0, 0] 了。

i=2 看到 2:当前是 2,和 r(下标 3)交换,r 退到 2。i 不动。

i=2 看到 1:换过来是 1,本来就该在中间,不用换,i 直接前进。此时 i 已经大于 r,扫描结束。

完成:一趟扫描完成排序:[0, 0, 1, 1, 2]

l 在左、r 在右各守一种值,中间是待处理区——这就是分区思想,快排的 partition 也类似。

参考代码(Python)

Python
1l, r, i = 0, len(nums)-1, 0
2while i <= r:
3    if nums[i] == 0:
4        nums[l], nums[i] = nums[i], nums[l]; l += 1; i += 1
5    elif nums[i] == 2:
6        nums[r], nums[i] = nums[i], nums[r]; r -= 1   # i 不动!
7    else: i += 1

复杂度分析

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

套路模板

记住骨架:l 守左、r 守右、i 扫描;换到右边后 i 不动。换一下条件就能复用:快排 partition、把某元素全移到末尾都是这套分区。

Python
1# 例: 0 归左、2 归右、1 留中(荷兰国旗)
2l, i, r = 0, 0, n - 1
3while i <= r:
4    if nums[i] == 0:                    # 该放左
5        nums[i],nums[l] = nums[l],nums[i]; l += 1; i += 1
6    elif nums[i] == 2:                  # 该放右
7        nums[i],nums[r] = nums[r],nums[i]; r -= 1   # i 不动!
8    else: i += 1                        # 中间值

易错点

  • 换到右边后 i 也前进 → ✅ 遇到 2 交换后 i 不动(从右边换来的值还没检查,可能是 0)
  • while i < len(nums) → ✅ while i <= r(r 右边已排好,i 越过 r 就该停)

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

下一题 →135. 分发糖果 ← 返回题库