📌  相关文章
📜  未排序数组中的第 K 个最小最大元素 |设置 1(1)

📅  最后修改于: 2023-12-03 15:26:32.113000             🧑  作者: Mango

未排序数组中的第 K 个最小/最大元素

在一个未排序的整数数组中,我们可以通过对其进行排序来找到第 k 个最小或最大的元素,但这个方法时间复杂度通常较高。本文将介绍两种使用快速选择(Quick Select)算法的方法,以便在 O(n) 的时间复杂度下找到第 k 个最小的或最大的元素。

什么是快速选择算法?

快速选择算法是一种基于快速排序算法的思想,用于查找未排序数组中的第 k 个元素。与快速排序不同的是,快速选择只需要对数组中的一部分进行递归,从而获得所需的元素,因此可以在 O(n) 的时间复杂度内解决这个问题。

方法一:使用快速选择算法

快速选择算法的基本思路如下:

  1. 选取一个枢轴元素(pivot),并将数组中小于枢轴的元素移到它的左侧,大于枢轴的元素移到它的右侧,将枢轴放在它的正确位置上。
  2. 如果枢轴恰好是第 k 个元素,直接返回它。
  3. 如果 k 小于枢轴的索引,递归数组的左半部分。
  4. 如果 k 大于枢轴的索引,递归数组的右半部分。

下面是 Java 语言的代码实现:

public int findKthLargest(int[] nums, int k) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int index = quickSelect(nums, left, right);
        if (index == k - 1) {
            return nums[index];
        } else if (index < k - 1) {
            left = index + 1;
        } else {
            right = index - 1;
        }
    }
    return -1;
}

private int quickSelect(int[] nums, int left, int right) {
    int pivot = nums[right];
    int i = left;
    for (int j = left; j < right; j++) {
        if (nums[j] >= pivot) {
            swap(nums, i, j);
            i++;
        }
    }
    swap(nums, i, right);
    return i;
}

private void swap(int[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

在上述代码中,findKthLargest 方法用于查找第 k 大的元素,quickSelect 方法实现了快速选择的核心算法,利用了快速排序的 partition 思想进行数组的快速排序。

方法二:使用堆排序

除了快速选择算法外,还可以使用堆排序来对数组进行排序,然后取得第 k 个元素。堆排序的时间复杂度为 O(nlogn),略高于快速选择,但实现起来相对简单。下面是 Python 语言的代码实现:

import heapq

def findKthLargest(nums, k):
    return heapq.nsmallest(k, nums)[-1]

在上述代码中,我们使用 heapq 模块的 nsmallest 函数,它能够返回数组中最小的 k 个元素,然后取最后一个元素即为第 k 大的元素。

总结

本文介绍了两种使用快速选择算法和堆排序算法来查找未排序数组中第 k 个最小或最大元素的方法。二者的时间复杂度都为 O(n),但快速选择的常数更小,一般来说比堆排序更快。