1. 题目分析
因为只需要求解最小k个部分,所以不一定需要对左右两半都进行递归。在代码上来说,只有递归部分和快排不同,分组部分不需要更改。
2. 左右部分的递归控制
左右部分递归控制方法如下:
(1)[l,...,r] ==> [l,..,p], [p+1,.., r]
(2)关注最小k个部分落在哪里:
i. 只落在左半时,p > k, 只在左半进行递归
ii. 至少有部分在右半时,p <= k, 只在右半进行递归
3. 代码
class Solution {
public:
int partation(int l, int r, vector<int>& arr) {
int pos = l;
for (int i=l; i<r; i++) {
if (arr[i] < arr[r]) {
swap(arr[i], arr[pos]);
pos++;
}
}
swap(arr[pos], arr[r]);
return pos;
}
// [l,...,r] ==> [l,..,p], [p+1,.., r]
// 关注最小k个部分落在哪里:
// 只落在左半时,p > k, 只在左半进行递归
// 至少有部分在右半时,p <= k, 只在右半进行递归
void qsort(int l, int r, int k, vector<int>& arr) {
if (l<r) {
int p = partation(l, r, arr);
if (p > k) qsort(l, p-1, k, arr);
if (p <= k) qsort(p+1, r, k, arr);
}
}
vector<int> smallestK(vector<int>& arr, int k) {
qsort(0, arr.size()-1, k, arr);
return vector<int>(arr.begin(), arr.begin()+k);
}
};