【快速排序】Acwing786.第k個數
阿新 • • 發佈:2022-05-07
Acwing786.第k個數
題解
快排本質上就是找出所取數在序列中的位置,再對其左右進行二分。
所以本題用快排可以以O(nlogn)複雜度解出。
#include <iostream> #include <cstdio> using namespace std; const int N = 100010; int q[N]; int quick_sort(int l, int r, int k) { if( l == r) return q[l]; int i = l - 1, j = r + 1, a = q[l + r >> 1]; while( i < j ) { do i ++ ; while(q[i] < a); do j -- ; while(q[j] > a); if( i < j ) swap(q[i], q[j]); } if(j - l + 1 >= k) return quick_sort(l, j, k); else return quick_sort(j + 1, r, k - (j + 1 - l)); } int main() { int n, k; scanf("%d%d",&n,&k); for(int i = 0; i < n; ++i) scanf("%d",&q[i]); printf("%d\n",quick_sort(0, n-1, k)); return 0; }
快排分析
該快排雖然只進行了區間劃分,但左邊小於等於x,右邊大於等於x這個位置不就是x在原序列的位置。
同時我們要對k在左右的情況進行討論:
k在劃分後的左邊(k <= j - l + 1): k不用進行改變,因為計算k的左邊界並沒有改變
k在劃分後的右邊(else): k需要進行改變,因為我們會對右區間進行快排,右區間的左邊界發生了改變,k作為計數也需要改變,k要減去左邊界在原來區間的位置再+1即:k = k - (j + 1 - l + 1) + 1 = k - (j + 1 - l)