TopK问题:就是给你一些数,让你从中找出最大/小的k个数
TopK问题有很多解法,如:堆、二叉排序树…
这里主要介绍利用了快速排序思想的快速选择做法
(如果没有学过快速排序,最好先去学习快速排序)
我们知道,快速排序每次partition之后都会把枢轴元素放到它的最终位置上,partition过程的操作如下:
每次选取一个元素 x 作为枢轴(一般选第一个元素),从后往前找比 x 小的第一个元素 y 放到 x 原来的位置上,再从前往后找比 x 大的第一个元素 z 放到 y 原来的位置上,最后把枢轴元素 x 放到 z 原来的位置上,这个位置就是 x 排完序的最终位置。此时 x 之前的元素都比 x 小,x 之后的元素都比 x 大。
因此,我们需要找最小的 k 个数(并不在意最小的 k 个数的顺序),就是看此时枢轴元素的前面是否是 k 个元素,如果大于 k,说明多了,就往左找,小于 k 个,说明少了,就往右找。
class Solution {
public:
int partition(vector<int>& nums, int i, int j) {
int pivot = nums[i];
while (i < j) {
while (i < j && nums[j] >= pivot) --j;
nums[i] = nums[j];
while (i < j && nums[i] <= pivot) ++i;
nums[j] = nums[i];
}
nums[i] = pivot;
return i;
}
int quickSelect(vector<int>& nums, int i, int j, const int& k) {
if (i < j) {
int pivotPos = partition(nums, i, j);
if (pivotPos == k) return k;
else if (pivotPos > k) quickSelect(nums, i, pivotPos - 1, k);
else quickSelect(nums, pivotPos + 1, j, k);
}
return k;
}
vector<int> getLeastNumbers(vector<int>& arr, int k) {
int i = quickSelect(arr, 0, arr.size() - 1, k);
return vector<int>(arr.begin(), arr.begin() + i);
}
};