45. 数组中的第 K 个最大元素
题目描述
给定一个整数数组 nums 和一个整数 k,返回该数组中第 k 个最大的元素。注意需要找的是排序后第 k 大的数,而不是第 k 个不同的元素。
解法:快速选择算法
思路解析
在传统的快速排序中,我们将数组分为小于、等于、大于基准值的三部分。利用这一特性,我们可以不必对整个数组进行完全排序。
核心逻辑是:通过随机选取基准值(Pivot)将数组划分为三个区间 [left, l](小于)、[l+1, r-1](等于)、[r, right](大于)。计算每个区间的元素数量,判断目标元素落在哪个区间内。如果落在右侧(大于区域),则递归处理右侧;如果落在中间(等于区域),则直接返回基准值;如果落在左侧,则调整 k 值继续递归左侧。
这种方法的时间复杂度平均为 O(N),远优于全排序的 O(NlogN)。
C++ 代码实现
class Solution {
public:
int Top_k(vector<int>& nums, int left, int right, int k) {
if (left == right) {
return nums[left];
}
// 随机选择基准元素,避免最坏情况
int key = nums[rand() % (right - left + 1) + left];
int l = left - 1, r = right + 1, i = left;
// 三路划分:大于、等于、小于
while (i < r) {
if (nums[i] > key) {
swap(nums[i], nums[--r]);
} else if (nums[i] < key) {
swap(nums[i++], nums[++l]);
} else {
i++;
}
}
// 若右边区域元素个数 >= k,说明第 k 大的数在右边区域
if (right - r + >= k) {
(nums, r, right, k);
}
(right - l >= k) {
key;
}
{
(nums, left, l, k - (right - l));
}
}
{
(());
(nums, , nums.() - , k);
}
};


