这道力扣HOT100系列的第75题"颜色分类"是一个经典的荷兰国旗问题变种。题目要求我们将一个仅包含0、1、2的数组原地排序,使得所有0排在前面,1在中间,2在最后。看似简单的需求背后隐藏着对双指针技巧和快速排序思想的深度考察。
在实际工程中,类似的三分类问题非常常见。比如电商系统中的订单状态筛选(待付款/已发货/已完成)、日志系统的错误等级分类(info/warning/error)等场景。这道题的特殊性在于要求:
传统排序算法如快速排序虽然能解决问题,但无法满足O(n)时间复杂度的要求。荷兰国旗问题的经典解法是使用三指针:
这种设计实现了:
具体操作时需要特别注意指针的移动逻辑:
python复制def sortColors(nums):
left, current, right = 0, 0, len(nums) - 1
while current <= right:
if nums[current] == 0:
nums[left], nums[current] = nums[current], nums[left]
left += 1
current += 1
elif nums[current] == 2:
nums[current], nums[right] = nums[right], nums[current]
right -= 1
else:
current += 1
关键点解析:
实际编码中最容易出现的错误是:
完整的测试应该包含:
python复制test_cases = [
([2,0,1], [0,1,2]), # 基础乱序
([2,2,2], [2,2,2]), # 全2场景
([0,0,0], [0,0,0]), # 全0场景
([1,1,1], [1,1,1]), # 全1场景
([2,0,2,1,1,0], [0,0,1,1,2,2]) # 混合复杂案例
]
虽然计数排序可以实现:
python复制def sortColors(nums):
count = [0]*3
for num in nums:
count[num] += 1
nums[:] = [0]*count[0] + [1]*count[1] + [2]*count[2]
但这种方法:
当需要处理更多类别时(如0-4共5类),可以采用:
在实际项目中使用类似算法时需要注意:
关键经验:当遇到需要保持相对顺序的类似问题时,应该考虑使用stable partition算法而非简单的双指针交换。
| 算法类型 | 时间复杂度 | 空间复杂度 | 是否原地 | 适用场景 |
|---|---|---|---|---|
| 双指针法 | O(n) | O(1) | 是 | 元素种类少 |
| 计数排序 | O(n) | O(k) | 否 | 数据范围小 |
| 快速排序 | O(nlogn) | O(logn) | 是 | 通用场景 |
| 标准库排序 | O(nlogn) | O(n) | 视实现 | 生产环境 |
这道题在力扣题库中的定位是中等难度,但实际考察点非常典型。建议学习者:
我在最初练习时最容易犯的错误是在交换2之后又立即移动current指针,导致某些0被跳过。后来通过打印每次交换后的数组状态,才彻底理解了指针移动的边界条件。建议大家在遇到类似问题时,一定要用print调试法观察中间状态。