1. 程式人生 > 其它 >acwing-786. 第k個數

acwing-786. 第k個數

給定一個長度為 n 的整數數列,以及一個整數 k,請用快速選擇演算法求出數列從小到大排序後的第 k 個數。

輸入格式

第一行包含兩個整數 n 和 k。
第二行包含 n 個整數(所有整數均在 1∼10^9 範圍內),表示整數數列。

輸出格式

輸出一個整數,表示數列的第 k 小數。

資料範圍

1≤n≤100000,
1≤k≤n

輸入樣例:

5 3
2 4 1 5 3

輸出樣例:

3

方法一:

藉助快排中partition的思想,假設第一個數是要找的第k小的數,對待處理資料一輪partition過後,若這個數所在的位置處於陣列的

  1. 第k個位置,輸出該數,演算法完成
  2. 若所在位置<k,則對該元素為pivot的右邊部分的元素進行partition
  3. 若所在位置>k,則以該元素為pivot的左邊部分的元素進行partition

若隨機取pivot,平均時間複雜度為O(n)

這裡程式碼懶得隨機取了,AC

#include <bits/stdc++.h>

int nums[1000010];

int findMid(int low, int high, int k) {
    int pivot = nums[low], l = low, h = high;
    while (low < high) {
        while (low < high && nums[high] >= pivot) high--;
        nums[low] = nums[high];
        while (low < high && nums[low] <= pivot) low++;
        nums[high] = nums[low];
    }
    if (low == k) return pivot;
    else if (low < k) return findMid(low + 1, h, k);
    else return findMid(l, low-1, k);
}

int main() {
    int n, k, a, b;
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &(nums[i]));
    }
    printf("%d", findMid(1, n, k));
}