題目傳送門

一、理解感悟

1、這是快速排序模板的練習題。

2、不一樣的地方在於它可以利用快排模板,但卻不需要真的把所有資料排序完成,每次一分為二後,只關心自己所有的那一半,就是可以節約一半的遞迴。

3、由於是關心“位置”(第幾個),所以需要攜帶這個引數。

4、位置這個引數不是一成不變的,因為如果在左側,那麼就是原來的位置,如果在右側,那就需要減去整個左側的長度。

二、C++程式碼

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
int q[N]; /**
* 功能:利用快速排序對陣列進行排序
* 關鍵詞:小哨兵,分治(遞迴)
* @param q 要排序的陣列,注意:函式中陣列引數是按地址傳遞的,
* 就是能把原來的陣列修改掉,不是抄出來一份給函式處理的
* @param l 左起的下標位置
* @param r 右末的下標位置
*/
void quick_sort(int q[], int l, int r, int k) {
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while (i < j) {
do i++; while (q[i] < x);
do j--; while (q[j] > x);
if (i < j)swap(q[i], q[j]);
}
//這裡可以對原模板做出了一些優化,劃分邊界時,目標位置是在左還是在右,
//在哪邊就繼續排序哪些,另一個就不需要排序了,可以加快運算速度。
int p = j - l + 1;//左側長度
if (k <= p) quick_sort(q, l, j, k);//在左側排左側
else quick_sort(q, j + 1, r, k - p);//在右側排右側,但要注意位置值要有變化,要把左側長度減去
} int main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> q[i];
//呼叫快排模板
quick_sort(q, 1, n, k);
//輸出結果
printf("%d", q[k]);
return 0;
}