先任意找数组中的一个元素a,采用快速排序将数组进行一次划分,即将小于a的元素放在其左侧,大于a的元素放在其右侧。然后判断元素a是否满足题目为第k小的数,满足则直接输出,否则判断下一次在哪一区间进行划分。
和快速排序的算法基本一样,只是当找到第k小的数之后就直接退出了,时间复杂度为O(n)
//找第k小的数 #include <iostream> using namespace std; int find(int le,int ri,int a[])//找基准元素位置 { int base=a[le];//基准元素 while(le<ri) { while(le<ri&&a[ri]>=base)//从序列右端开始处理,大于基准的不变 ri--; a[le]=a[ri];//小于基准的交换到左边 while(le<ri&&a[le]<=base)//处理左端,小于基准的不变 le++; a[ri]=a[le];//大于基准的交换到右边 } //当左边的元素都小于base,右边的元素都大于base时,此时base就是基准元素,le或ri就是基准元素的位置 a[le]=base; return le; } void quick_pow(int le,int ri,int k,int a[]) { if(le>=ri) return; int pos=find(le,ri,a); if(k-1==pos) { cout<<a[k-1]<<endl; return ; } else if(k-1<pos) quick_pow(le,pos-1,k,a); else quick_pow(pos+1,ri,k,a); } int main() { int n, k; cin >> n >> k; int a[1000]; for (int i = 0; i < n; i++) cin >> a[i]; quick_pow(0, n - 1, k,a); return 0; }