LeetCode-075:颜色分类,荷兰国旗问题就是三段区间不变量

本题在线练习:LeetCode 75. 颜色分类 — 在线练习(免费 · 无需登录 · AI 辅助)(https://onefly.top/zero2Leetcode/playground.html?id=75)

配套刷题网站 Zero2Leetcode — 内置本地 OJ + AI 教练,零门槛开始刷 Hot 100。

题目概述

给定只包含 0,1,2 的数组 nums,原地排序,使相同颜色相邻,并按照 0,1,2 顺序排列。

要求原地,通常也希望一次遍历完成。

核心思路:维护三个区间(荷兰国旗)

用三个指针 p0, i, p2 维护不变量:

  • [0, p0) 全是 0
  • [p0, i) 全是 1
  • (p2, n-1] 全是 2
  • [i, p2] 是未知区域,靠 i 去扫描处理

nums[i]

  • 等于 0:与 p0 交换,p0 += 1, i += 1
  • 等于 1i += 1
  • 等于 2:与 p2 交换,p2 -= 1,但 i 不动(因为换过来的元素还没判断)

代码实现(Python,可直接提交)

from typing import List


class Solution:
    def sortColors(self, nums: List[int]) -> None:
        p0 = 0
        i = 0
        p2 = len(nums) - 1

        while i <= p2:
            if nums[i] == 0:
                nums[p0], nums[i] = nums[i], nums[p0]
                p0 += 1
                i += 1
            elif nums[i] == 1:
                i += 1
            else:
                nums[p2], nums[i] = nums[i], nums[p2]
                p2 -= 1

逐行拆解:为什么遇到 2 时 i 不能加?

因为 nums[i]nums[p2] 交换后,i 位置来了一个“未知元素”,可能是 0、1 或 2。

如果这时 i += 1,就会跳过它,导致区间不变量被破坏。

手动模拟(nums=[2,0,2,1,1,0])

初始:p0=0,i=0,p2=5

  • i=0 是 2:和 p2 交换 -> [0,0,2,1,1,2], p2=4, i 仍为 0
  • i=0 是 0:和 p0 交换(同位)-> [0,0,2,1,1,2], p0=1,i=1
  • i=1 是 0:交换 -> [0,0,2,1,1,2], p0=2,i=2
  • i=2 是 2:和 p2 交换 -> [0,0,1,1,2,2], p2=3, i=2
  • i=2 是 1:i=3
  • i=3 是 1:i=4 结束

复杂度分析

  • 时间复杂度:O(n),一次扫描
  • 空间复杂度:O(1),原地

总结

这题的价值在于建立“区间不变量”思维:

  • 指针不是随便移动的,每一步都在维护三段已经确定的区域
  • 交换不是为了排序本身,而是为了把元素扔进它应该属于的区间

把三段区间写清楚,代码就会自然且不容易错。

posted @ 2026-03-27 01:21  孤飞  阅读(11)  评论(0)    收藏  举报