文章目录
- Question
- Ideas
- Code
Question
给定一个长度为 n
 的整数数列,以及一个整数 k
 ,请用快速选择算法求出数列从小到大排序后的第 k
 个数。
输入格式
 第一行包含两个整数 n
 和 k
 。
第二行包含 n
 个整数(所有整数均在 1∼109
 范围内),表示整数数列。
输出格式
 输出一个整数,表示数列的第 k
 小数。
数据范围
 1≤n≤100000
 ,
 1≤k≤n
 输入样例:
 5 3
 2 4 1 5 3
 输出样例:
 3
Ideas
- 快速选择算法
- 每次让一半变得有序,需要判断k在哪个区间内,只需要让该区间有序即可
Code
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
int q[N];
int quick_choose(int q[], int l, int r, int k)
{
    if (l >= r) return q[l];
    
    int x = q[l + r >> 1];
    int i = l - 1, j = r + 1;
    
    while (i < j)
    {
        do i ++; while(q[i] < x);
        do j --; while(q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    
    int len_l = j - l + 1;
    if (k <= len_l) return quick_choose(q, l, j, k);
    else return quick_choose(q, j + 1, r, k - len_l);
}
int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    
    
    for (int i = 0; i < n; i ++)
    {
        scanf("%d", &q[i]);
    }
    
    printf("%d", quick_choose(q, 0, n - 1, k));
    
    return 0;
}
def quick_choose(q, l, r, k):
    if l >= r: 
        return q[l]
    
    i, j, x = l - 1, r + 1, q[l + r >> 1]
    
    while i < j:
        while 1:
            i += 1
            if (q[i] >= x):break
        while 1:
            j -= 1
            if (q[j] <= x): break
        
        if i < j:
            q[i], q[j] = q[j], q[i]
    
    len_l = j - l + 1
    
    if k <= len_l:
        return quick_choose(q, l, j, k)
    return quick_choose(q, j + 1, r, k - len_l)
if __name__ == '__main__':
    n, k = list(map(int, input().strip().split()))
    
    q = [int(i) for i in input().strip().split()]
    
    print(quick_choose(q, 0, n - 1, k))









![Vue中 引入使用 patch-package 为依赖打补丁 (以修改 vue-pdf 打包后 [hash].worker.js 路径问题为例)](https://img-blog.csdnimg.cn/5e1eeb3ab60b4e89942d3d47a72c1d71.png#pic_center)









