572 字
3 分钟
数组中的第K个最大元素

题目描述#

给定整数数组 nums 和整数 k,请返回数组中第 **k** 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

解题思路#

  1. 快速选择算法
    • 随机化分区:选取随机pivot将数组分为大于/小于pivot的两部分
    • 分治策略:根据pivot位置与k的关系,递归处理左或右子数组
    • 终止条件:pivot正好是第k大元素时返回
  2. 堆排序优化
    • 构建大小为k的最小堆
    • 遍历数组,维护堆顶为当前第k大元素
    • 最终堆顶即为结果

关键洞察#

  1. 快速选择本质:快速排序的变种,但只需处理目标所在分区
  2. 随机化避免最坏:随机选择pivot防止有序数组的O(n²)退化
  3. 堆的适用场景:海量数据流场景(空间效率高)
  4. 索引转换:第k大元素下标 = n - k(升序排序)

复杂度分析#

方法时间复杂度空间复杂度
快速选择平均O(n),最坏O(n²)递归栈O(log n)
堆方法O(n log k)O(k)
排序法O(n log n)O(1)

最优选择

  • 常规场景:快速选择(平均线性时间)
  • 内存受限:堆方法(仅需O(k)空间)
  • 巨量数据流:堆方法是唯一可行解

代码实现#

/**
* @link {https://leetcode.cn/problems/kth-largest-element-in-an-array}
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var findKthLargest = function (nums, k) {
const quickSelect = (num, l, r, k) => {
if (l === r) return num[k];
const x = num[l];
let i = l - 1, j = r + 1;
while (i < j) {
do i++; while (num[i] < x);
do j--; while (num[j] > x);
if (i < j) {
[num[i], num[j]] = [num[j], num[i]]
}
}
if (k <= j) {
return quickSelect(num, l, j, k);
} else {
return quickSelect(num, j + 1, r, k);
}
}
const n = nums.length;
return quickSelect(nums, 0, n - 1, n - k);
};

相似题目#

数组中的第K个最大元素
https://website-truelovings-projects.vercel.app/posts/algorithms/数组中的第k个最大元素/
作者
欢迎来到StarSky的网站!
发布于
2025-08-07
许可协议
CC BY-NC-SA 4.0