思路
求第k小的数,第一时间就能想到和排序有关,但这个数据量用冒泡排序什么的肯定会很糟糕,所以用到了快速排序
在快速排序时,我们先选取一个基准值,然后把数组中所有比基准值小的数放到基准值左边,比基准值大的数放到基准值右边,等于基准值的数任意放在哪一边。
每一次完成这样的操作以后,我们根据k和基准值的大小关系,选取左区间或右区间递归,直到区间里只剩一个数,那就是我们要的第k小数
代码
#include <iostream>
using namespace std;
int num[5000005];
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int deal(int left, int right, int k) {
//如果left和right相等,说明只剩第k小的数
if (left == right)return num[k];
int lPtr = left;
int rPtr = right;
//选区间中间的值为基准值进行快速排序
int pivot = num[(left + right) >> 1];
while (lPtr <= rPtr) {
while (num[lPtr] < pivot)lPtr++;
while (num[rPtr] > pivot)rPtr--;
if (lPtr <= rPtr) {
swap(num[lPtr], num[rPtr]);
lPtr++;
rPtr--;
}
}
//运行完上面的循环以后rPtr在lPtr的左边
//根据k的位置选择区间递归
if (k <= rPtr)return deal(left, rPtr, k);
return deal(lPtr, right, k);
}
int main() {
int T; //数据组数
T = read();
int n; //数列长度
int k; //求第k小的数
while (T-- > 0) {
n = read();
k = read();
for (int i = 0; i < n; ++i) {
num[i] = read();
}
cout << deal(0, n, k) << endl;
}
} 
京公网安备 11010502036488号