1. 程式人生 > 其它 >【快速排序】Acwing786.第k個數

【快速排序】Acwing786.第k個數

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)