考点
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <bits/stdc++.h>
using namespace std;
const int LEN = 5e6 + 10;
int K, arr[LEN];
int k_th(int arr[], int len) { if (len <= 1) return arr[0]; int i = 0, j = 0, k = len, pivot = arr[rand() % len]; while (i < k) { if (arr[i] < pivot) swap(arr[i++], arr[j++]); else if (arr[i] > pivot) swap(arr[i], arr[--k]); else ++i; } if (K < j) return k_th(arr, j); else if (K >= k) { K -= k; return k_th(arr + k, len - k); } else return pivot; }
int main() { ios::sync_with_stdio(false); int n; cin >> n >> K; for (int i = 0; i < n; ++i) cin >> arr[i]; cout << k_th(arr, n); return 0; }
|
思路
不同题目对第K大和第K小都有不同的定义;就本题而言,是求升序数列中的第K个元素,K从0开始
可以联想到三路快排算法:每次都以pivot
为标准,左半部分均小于pivot
,中间部分等于pivot
,右半部分大于pivot
所以只需要判断K处在哪一个部分:
- K在左半部分,向左半部分递归
- K在中间部分,直接返回结果,因为中间部分的值都是相同的
- K在右半部分,K先减去左半部分加中间部分的长度,以转换为右半部分子数组的下标,再向右半部分递归