第k小的数
鏈接:第k小的數
來源:牛客網
數據范圍5e6
題目描述
給你一個長度為n的序列,求序列中第k小數的多少。
輸入描述:
多組輸入,第一行讀入一個整數T表示有T組數據。
每組數據占兩行,第一行為兩個整數n,k,表示數列長度和k。
第二行為n個用空格隔開的整數。
輸出描述:
對于每組數據,輸出它的第k小數是多少。
每組數據之間用空格隔開
示例1
輸入
復制
2
5 2
1 4 2 3 4
3 3
3 2 1
輸出
復制
2
3
分析
STL中的nth_element 函數可以過
下面學習一下nth_element的用法
該函數就是找第n小的數的位置,但是沒有返回值。小于等于n_th的數放在前面,大于等于n_th的數放在后面,但是[begin,nth)和(nth,end)這兩個區間并不保證有序。
用法:中間放的是nth
測試代碼
#include<bits/stdc++.h> using namespace std; set<int> s; const int maxn=5e6; int t,n,k; int a[maxn];int read(){int k=0,f=1;char c=getchar();while(c<'0'||c>'9'){if (c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){k=k*10+c-'0';c=getchar();}return f*k; } int main(){ scanf("%d%d",&n,&k);for(int i=0;i<n;i++){a[i]=read();}nth_element(a,a+k,a+n);cout<<"nth_element之后:"<<endl;for(int i=0;i<n;i++)cout<<a[i]<<" ";cout<<endl;printf("第%d小的數是:%d",k,a[k]);return 0; }測試一下
發現:只有n_th是有序的,前半部分無序,后半部分無序。
ac代碼
下面給一種快排的思路
復習一下快排的基本思想
step1:選擇分界點 一般 x=q[(l+r)/2]
step2: 使得左半邊區間的數小于等于 x,右半邊區間的數大于等于x
方法是使用頭尾指針,指針的邊界是兩者相遇
step3:遞歸快排左右兩個區間
這里需要借鑒快排的思想
找第k小的數
step1:選擇分界點:x
step2:記左半邊區間小于等于k 的個數為S1,右半邊區間小于等于k的個數為k-S1
如果k≤s1,說明第k小的數一定在左半邊,只需要遞歸左半邊區間即可
如果k>s1,說明第k小的數一定在右半邊,此時需要遞歸右半邊的區間。
ac代碼(不含重復的數字)
#include<iostream> #include<algorithm> using namespace std;const int maxn=1e5+10; int n,k,a[maxn]; int quick_sort(int l ,int r, int k){//第k小數是在區間l和r里面的if(l==r) return a[l];int x=a[l+r>>1];int i=l-1,j=r+1;while(i<j){do i++;while(a[i]<x);do j--;while(a[j]>x);if(i<j) swap(a[i],a[j]);}int sl=j-l+1;if(k<=sl) return quick_sort(l,j,k);else return quick_sort(j+1,r,k-sl);}int main(){scanf("%d%d",&n,&k);for(int i=0;i<n;i++) scanf("%d",&a[i]);cout<< quick_sort(0,n-1,k)<<endl;}總結
- 上一篇: happy card 完全背包dp
- 下一篇: 姓韦和姓章怎么取网名?