1. 问题背景与需求分析
这道题目来自力扣(LeetCode)的热门100题系列,编号75题"颜色分类"。题目要求对一个仅包含0、1、2的数组进行原地排序,其中0代表红色,1代表白色,2代表蓝色。这就是经典的荷兰国旗问题(Dutch National Flag Problem),由计算机科学家Edsger Dijkstra提出。
在实际工程中,这类问题常见于:
- 图像处理中的像素分类
- 物流系统中的货物分拣
- 数据统计中的快速分组
注意:题目明确要求必须使用原地排序算法,空间复杂度应为O(1),这意味着不能使用额外的存储空间。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法思路解析
2.1 暴力解法与局限性
最直观的解法是直接调用语言内置的排序函数,例如Python中的sort()方法。但这种解法:
- 不满足"原地排序"的要求(某些语言的sort实现可能使用额外空间)
- 时间复杂度通常为O(nlogn),不是最优解
- 没有利用到元素取值有限的特性
python复制# 不推荐的暴力解法
def sortColors(nums):
nums.sort()
2.2 计数排序法
由于元素取值只有0、1、2三种可能,可以采用计数排序:
- 第一次遍历统计0、1、2的个数
- 第二次遍历按统计结果重写数组
python复制def sortColors(nums):
count = [0, 0, 0]
for num in nums:
count[num] += 1
nums[:] = [0]*count[0] + [1]*count[1] + [2]*count[2]
虽然时间复杂度是O(n),但需要两次遍历,且实际上还是使用了额外空间(count数组)。
2.3 三指针法(最优解)
最优解法是使用三个指针进行单次遍历:
- left:指向当前0的右边界
- right:指向当前2的左边界
- curr:当前处理的元素
算法流程:
- 初始化left=0, right=len(nums)-1, curr=0
- 当curr <= right时:
- 如果nums[curr] == 0:与nums[left]交换,left++, curr++
