./remake 算法 - 快速选择

快速选择算法一般常用于选第K大(小)的数,其时间复杂度是O(n)的。

主要思想还是快速排序,就是在快速排序的基础上,加个if-else,往其中一个方向递归处理即可。

其基本流程如下:

  • 确定分界点:一般是中间点(l + r) / 2、(l + r + 1) / 2,或随机值。
  • 调整区间:小于分界点x的在左边,大于分界点y的在右边。
  • 递归处理K所在左段或右段(二选一)。

整体程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>

using namespace std;

int quick_select(int *nums, int l, int r, int k) {
if (l >= r) {
return nums[l];
}

int i = l - 1, j = r + 1;
int x = nums[(l + r) / 2];
while (i < j) {
do i++; while(nums[i] < x);
do j--; while(nums[j] > x);
if (i < j) swap(nums[i], nums[j]);
}
if (j - l + 1 >= k) return quick_select(nums, l, j, k);
else return quick_select(nums, j + 1, r, k - (j - l + 1));
}

int main() {
int N, k;
cin >> N >> k;

int nums[N];
for (int i = 0; i < N; i++) {
cin >> nums[i];
}

cout << quick_select(nums, 0, N - 1, k) << endl;
}

综上,快排(快速选择)最难的还是避免无限递归,需要牢牢记住:

  1. 分界点取中间(l + r) / 2时,递归处理左右两段应该是[l, j]和[j+1, r]

  2. 分界点取中间(l + r + 1) / 2时,递归处理左右两段应该是[l, i-1]和[i, r]

同时,判断第K大的数字在哪个区间也很重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值