数组中的第 K 个最大元素 问题

4 阅读1分钟

数组中的第 K 个最大元素 问题

方法一:排序法

最直接的方法是先对数组进行排序,然后取第 K 个最大的元素。这种方法的时间复杂度为 O(n log n)。

int findKthLargest(vector<int>& nums, int k) {
  std::sort(nums.begin(), nums.end(), greater<int>());
  return nums[k - 1];
}

方法二:使用最小堆

可以利用最小堆(Min-Heap)来实现,这种方法的时间复杂度为 O(n log k)。具体步骤如下:

步骤:

  1. 创建一个大小为 K 的最小堆。
  2. 遍历数组,将元素依次插入堆中。如果堆的大小超过 K,则弹出堆顶元素。
  3. 遍历结束后,堆顶元素即为第 K 个最大元素。
int findKthLargest(vector<int>& nums, int k) {
  priority_queue<int, vector<int>, greater<int>> pq;
  for (int i = 0; i < nums.size(); i++) {
    pq.push(nums[i]);
    if (pq.size() > k) {
      pq.pop();
    }
  }
  return pq.top();
}

方法三:快速选择算法(Quickselect)

快速选择算法是快速排序(Quicksort)的一个变种,时间复杂度为 O(n) 平均时间复杂度,但在最坏情况下为 O(n²)。

步骤:

  1. 选择一个枢轴元素。
  2. 通过一次划分操作将数组分为两部分:左边部分小于枢轴,右边部分大于枢轴。
  3. 判断第 K 个最大元素位于哪一部分,递归处理。

void quick_select(vector<int>& nums, int left, int right, int k) {
  if (left >= right) return;
  int l = left, r = right;
  int pivot = nums[left + (right - left) / 2];
  while (l <= r) {
    while (l <= r && nums[l] > pivot) ++l;
    while (l <= r && nums[r] < pivot) --r;
    if (l <= r) {
      swap(nums[l], nums[r]);
      ++l;
      --r;
    }
  }
  if (k <= r) quick_select(nums, left, r, k);
  if (k >= l) quick_select(nums, l, right, k);
}

int findKthLargest(vector<int>& nums, int k) {
  quick_select(nums, 0, nums.size() - 1, k - 1);
  return nums[k - 1]; 
}