首先,本题可以直接用nth_element解决。
如果自己写的话本题明显是在快速排序的基础上做一些改进。快速排序每一趟可以将一个元素归位,学过数据结构的应该可以理解,所以我们只需要在快速排序每一趟结束的时候判断一下这一趟排好的元素是不是第k位的元素,不是的话继续递归。注意递归中不需要所有的元素都递归,只递归包含有第k位元素的区间,相当于剪枝。
需要注意,如果使用cin,cout需要关闭同步流提高输入输出效率,否则后两个测试点会超时。
由于我不会快速排序,我先找了一份快排的代码学习了一下,如果有不会快排的也可以一起学习。
#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left, int right) {
int i, j, t, temp;
if(left > right){//若left指向在right指向右边,排序结束
return;
}
temp = a[left]; //temp中存的就是基准数,一般最开始时left为1,
//即最开始基准数是从左往右数第一个数
i = left;
j = right;
while(i != j) { //顺序很重要,要先从右边开始找
while(a[j] >= temp && i < j){ //先找右边的
j--;
}
while(a[i] <= temp && i < j){//再找左边的
i++;
}
//以上步骤找到左边从左到右首个小于temp的数,
//和从右往左数首个大于temp的数
if(i < j)//交换两个数在数组中的位置
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//最终将基准数归位,即排序的最后a[i]要小于基准字,将a[i]赋值给基准字
a[left] = a[i];
a[i] = temp;//temp中保存着基准字的值,将基准字的值放到a[i]的位置上
quicksort(left, i-1);//继续处理左边的,这里是一个递归的过程
quicksort(i+1, right);//继续处理右边的 ,这里是一个递归的过程
}
int main() {
int i;
//读入数据
scanf("%d", &n);
for(i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
quicksort(1, n); //快速排序调用
//输出排序后的结果
for(i = 1; i < n; i++){
printf("%d ", a[i]);
}
printf("%d\n", a[n]);
return 0;
}
在此基础上我的代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[5000005];
int qsort(int l, int r, int k)
{
if (l > r)
{
return -1;
}
int temp = a[l];
int i = l, j = r;
while (i < j)//从右边找起,右边默认大于标定值,左边默认小于
{
while ((temp <= a[j]) && (i < j))//找到右边比标定值小的数的下标
j--;
while ((temp >= a[i]) && (i < j))//找到左边比标定值大的数的下标
i++;
if (i < j)
{
swap(a[i], a[j]);
}
}
//现在只有标定值和中间的值a[i]没有归位
swap(a[i], a[l]);//归位
if (k == i)//找第k小的值
return a[k];
if (k < i)//未找到就递归查找
return qsort(l, i - 1, k);
if (k > i)//相当于剪枝,提高速度
return qsort(i + 1, r, k);
}
int main() {//注意k从0开始
//用于关闭同步流提高输入输出效率
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//
int m, n;
cin >> m >> n;
for (int i = 0; i < m; i++)
{
cin >> a[i];
}
cout << qsort(0, m - 1, n) << endl;
return 0;
}