快速选择算法(Quickselect)是一种在数组中查找第K大元素的算法。它与快速排序算法非常相似,只是找到第K大元素后就停止递归。
我们可以实现快速选择算法如下:
public int quickselect(int[] nums, int k) {
return quickselect(nums, 0, nums.length - 1, k);
}
private int quickselect(int[] nums, int left, int right, int k) {
// 1. 递归终止条件
if (left == right) return nums[left];
// 2. 选择pivot并划分数组
int pivotIndex = partition(nums, left, right);
// 3. 确定K属于左部分或右部分
if (k <= pivotIndex - left)
return quickselect(nums, left, pivotIndex - 1, k);
else
return quickselect(nums, pivotIndex + 1, right, k - (pivotIndex - left + 1));
}
private int partition(int[] nums, int left, int right) {
int pivot = nums[left];
int j = left;
for (int i = left + 1; i <= right; i++) {
if (nums[i] < pivot) {
j++;
swap(nums, j, i);
}
}
swap(nums, left, j);
return j;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
算法流程:
- 递归终止:当left == right,找到第K大元素。
- 选择pivot并划分数组,返回pivot位置index。
- 判断K属于左部分或右部分,递归查找。
- 不断划分数组并递归,直到找到第K大元素。
时间复杂度O(n),空间复杂度O(logn)。
所以,快速选择算法的关键是:
- 使用快速排序中的pivot选取与划分数组方法。
- 递归终止条件:left == right。
- 判断k属于左部分或右部分,相应递归。
- 通过不断划分数组和递归,找到第k大元素。
与快速排序算法相比,找到第K大元素后直接返回,不继续递归划分与排序。