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

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

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

在给定一个未排序的整数数组中,找到第 K 个最小的元素或者第 K 个最大的元素。这个问题可以通过排序解决,但是排序的时间复杂度是 O(nlogn),比较高。我们可以使用其他算法来更快地解决这个问题。

解法一:快速选择算法

快速选择算法使用了快速排序算法的思想。首先将数组按照某个元素(pivot)进行划分,然后根据划分的结果来决定在哪个子数组中继续查找第 K 个最小/最大元素。假设我们要查找第 K 个最小元素,我们可以按照以下步骤:

  1. 选择一个 pivot,并将数组划分为两个子数组,左边的数组元素均小于等于 pivot,右边的数组元素均大于 pivot。

  2. 如果左边的数组元素个数大于等于 K,那么递归地在左边的数组中查找第 K 个最小元素。

  3. 如果左边的数组元素个数小于 K,那么递归地在右边的数组中查找第 K-len(left)-1 个最小元素。

时间复杂度:O(n) ~ O(n^2)

代码实现:

def quick_select(nums, k):
    """
    在 nums 中查找第 k 个最小元素
    """
    if not nums:
        return None
    pivot = nums[0]
    left = [x for x in nums if x < pivot]
    mid = [x for x in nums if x == pivot]
    right = [x for x in nums if x > pivot]
    if k <= len(left):
        return quick_select(left, k)
    elif k > len(left) + len(mid):
        return quick_select(right, k - len(left) - len(mid))
    else:
        return mid[0]
解法二:堆排序算法

我们可以使用堆排序算法来查找第 K 个最小/最大元素。堆是一个完全二叉树,并满足堆属性:对于每个节点 x,x 的父节点的值小于等于 x 的值。堆可以用数组表示,其中下标为 i 的元素的父节点下标为 (i-1)/2,左子节点下标为 2i+1,右子节点下标为 2i+2。

对于第 K 个最小元素,我们可以建立一个最大堆,然后依次删除堆顶元素,直到取出 K 个元素即可。对于第 K 个最大元素,我们可以建立一个最小堆,然后依次删除堆顶元素,直到取出 K 个元素即可。

时间复杂度:O(nlogn)

代码实现:

import heapq

def kth_smallest(nums, k):
    """
    在 nums 中查找第 k 个最小元素
    """
    if not nums or k < 1 or k > len(nums):
        return None
    heap = [-x for x in nums[:k]]
    heapq.heapify(heap)
    for i in range(k, len(nums)):
        if -nums[i] > heap[0]:
            heapq.heappop(heap)
            heapq.heappush(heap, -nums[i])
    return -heap[0]

def kth_largest(nums, k):
    """
    在 nums 中查找第 k 个最大元素
    """
    if not nums or k < 1 or k > len(nums):
        return None
    heap = nums[:k]
    heapq.heapify(heap)
    for i in range(k, len(nums)):
        if nums[i] > heap[0]:
            heapq.heappop(heap)
            heapq.heappush(heap, nums[i])
    return heap[0]