P1293 求第k小的數
阿新 • • 發佈:2021-11-11
\(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)\)即可