解题思路
采用快排的思想,每次确定第k小数所在的区间,直到区间只剩下一个元素,或者k处在mid位置
AC代码
#include <iostream> using namespace std; const int N=5000010; int a[N]; int finding(int l,int r,int k) { if(l==r) return a[l]; int i=l,j=r; int mid=(l+r)>>1; int x=a[mid]; while(i<=j) { while(a[j]>x) j--; while(a[i]<x) i++; if(i<=j) { swap(a[i],a[j]); i++,j--; } } if(k<=j) return finding(l,j,k); else if(k>=i) return finding(i,r,k); else return a[k]; } inline 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<<1) + (x<<3) + (ch^48); ch = getchar(); } return x * f; } int main() { int t; t=read(); int n,k; while(t--) { n=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(); printf("%d\n",finding(1,n,k)); } return 0; }
注意
a[mid]的值要用一个变量x代替,在交换的过程中,mid位置上的元素会发生改变
还可以使用STL库函数nth_element()求第k小数
#include <bits/stdc++.h> using namespace std; const int N=5000010; int a[N]; static char buf[100000], * pa = buf, * pb = buf; #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),pa==pb)?EOF:*pa++ inline long long int read() { long long int x(0); char c(gc); while (c < '0' || c>'9')c = gc; while (c >= '0' && c <= '9')x = (x << 1) + (x << 3) + (c ^ 48), c = gc; return x; } int main() { int t; t=read(); int n,k; while(t--) { n=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(); nth_element(a+1,a+k,a+n+1); printf("%d\n",a[k]); } return 0; }