给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
解答:
- 快速选择算法
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
return quickSelect(nums, k);
}
private:
int quickSelect(vector<int>& nums, int k) {
int pivot = nums[rand() % nums.size()];
vector<int> big, small;
for (int num : nums) {
if (num > pivot)
big.push_back(num);
else if (num < pivot)
small.push_back(num);
}
if (k <= big.size())
return quickSelect(big, k);
if (nums.size() - small.size() < k)
return quickSelect(small, k - nums.size() + small.size());
return pivot;
}
};
- 摸鱼解法(sort快排)
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
return nums[nums.size() - k];
}
};
思路:仅解法1 2 sort 快排不用解释
主函数调用快速选择算法函数找到第 k 大的元素,
快速选择算法中先随机选择基准数,
将大于和小于基准数的元素分别放入 big 和 small 数组中,
进而检查两个条件来确定第k大的元素的位置:
如果k小于或等于big向量的长度,那么第k大的元素在big向量中。递归调用quickSelect(big, k)来查找第k大的元素。
如果数组中剩余的元素(即nums.size() - small.size())小于k,那么第k大的元素在small向量中。
递归调用quickSelect(small, k - nums.size() + small.size())来查找第k大的元素。
否则,返回枢轴元素,它就是第k大的元素。
问题:为什么要随机选择基准数?
在待排数组是大部分呈现有序时,从固定位置选取会使得排序效率降低,为了缓解这种情况,就引入了随机选取