分治思想在排序与选择问题中的应用
分治(Divide and Conquer)是算法设计中的核心范式之一。通过递归地将大问题分解为小问题,我们往往能显著降低时间复杂度。本文将结合 LeetCode 上的经典题目,深入探讨基于快速排序思想的三种变体应用:颜色分类、数组排序、TopK 问题以及最小 K 个数。
一、颜色分类(荷兰国旗问题)
LeetCode 75. Sort Colors
给定一个包含红色(0)、白色(1)和蓝色(2)的数组,要求原地排序,使得相同颜色的元素相邻并按顺序排列。关键约束是不使用库内置的 sort 函数。
思路解析
我们可以利用三指针法将数组划分为四个区域:
[0, left]:全是 0[left+1, i-1]:全是 1[i, right-1]:待扫描区域[right, n-1]:全是 2
其中 left 指向 0 区域的右边界,right 指向 2 区域的左边界,i 是当前扫描位置。
遍历过程中根据 nums[i] 的值进行决策:
- 遇到 0:交换
nums[++left]和nums[i],然后i++。注意这里先移动left再交换,确保left始终指向已处理好的 0 区域末尾。 - 遇到 1:直接
i++,因为 1 位于中间区域,无需交换。 - 遇到 2:交换
nums[--right]和nums[i]。关键点:此时i不增加,因为从右侧换过来的元素尚未被检查,需要再次判断。
当 i 与 right 相遇时,扫描结束。
class Solution {
public:
void sortColors(vector<int>& nums) {
int n = nums.size();
int left = -1, right = n, i = 0;
while (i < right) {
if (nums[i] == 0) swap(nums[++left], nums[i++]);
else if (nums[i] == 1) i++;
else (nums[--right], nums[i]);
}
}
};


