题目传送门:https://www.luogu.com.cn/problem/P1923
题目概述
本题的要求是在很多数中找出第k小的数,由于本题的数很多,所以不能直接用sort排序(会超时)。
思路分析
既然不能用sort(时间复杂度是nlogn),那么就要想办法将时间复杂度降到O(n)。首先想到的方法肯定是二分,也就是快速排序。这里我们先回顾一下快速排序的过程,首先是选择一个mid下标值,然后以这个mid值为基准,将所有的数分成小于mid和大于mid的两堆,然后整一堆数就分成了两部分。然后比较一下当前的中间值和k的大小关系,如果比k小的话,就再次快排左边,如果比k大的话就快排右边,如果正好等于k,直接输出即可。
满分代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int m,k;
int a[5000005];
void qsort(int l,int r)
{
int i=l,j=r,mid=a[(l+r)/2];//注意mid的写法
while(i<=j)
{
while(a[i]<mid)
i++;
while(a[j]>mid)
j--;
if(i<=j)//原来写成a[i] a[j]的关系了
{
swap(a[i],a[j]);
i++;
j--;
}
}
if(k<=j)
qsort(l,j);
else if(k>=i)
qsort(i,r);
else
{
printf("%d",a[j+1]);
exit(0);
}
}
int main()
{
cin>>m>>k;
for(int i=0;i<m;i++)
{
scanf("%d",&a[i]);
}
qsort(0,m-1);
return 0;
}
注意事项
这里要注意以下几个问题:
1、首先是mid的写法,mid是对于下标而言的,不是对于中间这个下标对应的数值的!!!!
2、判断的时候注意条件是i和j的关系,不是a[i]和a[j]的关系。