P1293 求第k小的数

\(Description\)

输入\(n\)个数字及\(k\),求第\(k\)(\(k\)从0编号)小的数
(\(n<=5e6,ai<=10^9\))

\(Solution1\)

这道题数据范围显然不能用一般排序硬做,再\(O(1)\)查询
考虑快速排序,每次确定基准值归位后对左右继续递归,此时基准值是在他应该的位置上的(也就是说基准值是第\(p\)小,那他排完序一定在\(a[p]\)
而对于这道题,我们并不需要考虑把所有数排序,比如基准值是第\(i\)大,那么若\(k<i\),只需要对\((l,i-1)\)递归,若\(k>i\),只需要对\((i+1,r)\)递归,直到\((i==k)\)
,显然平均复杂度为\(O(n)\)

\(Code 1\)

#include<iostream>
#include<cstdio>
 #include<algorithm>
#include<cstring>
#include<string>
#define re register
#define maxn 5000010 
#define ll long long
using namespace std;
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*10+ch-'0';ch=getchar();}
	return x*f;
}
int n,a[maxn],k;
void quicksort(int l,int r)
{
	if(l>=r) return;
	int i=l,j=r,base=a[l];
	while(i<j)
	{
		while(a[j]>=base&&i<j) j--;
		while(a[i]<=base&&i<j) i++;
		swap(a[i],a[j]); 
	}
	swap(a[l],a[i]);
	if(i==k) return;
	if(i>k) quicksort(l,i-1);
	else quicksort(i+1,r);
}
int main()
{
    n=read(),k=read();
    k++;
    for(re int i=1;i<=n;++i) a[i]=read();
    quicksort(1,n);
    printf("%d",a[k]); 
	return 0;
}

\(Solution2\)

可以借助\(STL\)函数\(nth_element\),声明在\(algorithm\)
用法如下
\(nth_element(a+x,a+x+y,a+x+len);\)
表示对\(a[x]\)\(a[x+len-1]\)操作,保证\(a[x]~a[x+y-1]\)的数全部小于\(a[x+y]\),\(a[x+y+1]~a[x+len-1]\)的数全部大于\(a[x+y]\),但不保证顺序
也就是说,保证了\(a[x+y]\)存放的是\(a[x]~a[x+len-1]\)中第\(y+1\)小的数
此题写\(nth_element(a,a+k,a+n)\)即可

posted @ 2021-11-11 17:42  __Liuz  阅读(32)  评论(0编辑  收藏  举报