1. 程式人生 > 其它 >P1293 求第k小的數

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)\)即可