LeetCode 251:数组中的第K个最大元素(快速排序、堆排序)

本文介绍了如何通过改进快速排序算法实现快速选择,利用随机选择枢轴提高查找第k大元素的效率,同时讨论了使用小顶堆来高效地找出数组中的第k大元素。讲解了两种方法的具体实现和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

快速排序

快速排序是一个典型的分治算法,每次经过「划分」操作后,一定可以确定一个元素的最终位置,并且保证该元素左边的元素都小于等于它,右边的元素都大于等于它。所以只要某次划分的元素位置q为倒数第 k个下标的时候,我们就已经找到了答案。
因此我们可以改进快速排序算法来解决这个问题:在分解的过程当中,我们会对子数组进行划分,如果划分得到的 q正好就是我们需要的下标,就直接返回 a[q];如果 q 比目标下标小,就递归右子区间,否则递归左子区间。这样就可以把原来递归两个区间变成只递归一个区间,提高了时间效率。这就是「快速选择」算法。

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        def partition(nums, left, right):
            import random
            p = random.randint(left, right)
            nums[left], nums[p] = nums[p], nums[left]
            pivot = nums[left]  # 初始化一个待比较数据
            i, j = left, right
            while(i < j):
                while(i < j and nums[j] >= pivot):  # 从后往前查找,直到找到一个比pivot更小的数
                    j -= 1
                nums[i] = nums[j]  # 将更小的数放入左边
                while(i < j and nums[i] <= pivot):  # 从前往后找,直到找到一个比pivot更大的数
                    i += 1
                nums[j] = nums[i]  # 将更大的数放入右边
            # 循环结束,i与j相等
            nums[i] = pivot  # 待比较数据放入最终位置
            return i  # 返回待比较数据最终位置
        left, right, p = 0, len(nums)-1, len(nums)-k
        while True:
            while left < right:
                index = partition(nums, left, right)
                if index == p:
                    return nums[index]
                elif index < p:
                    left = index + 1
                else:
                    right = index - 1
            return nums[left]

如果直接选择左端点或右端点作为轴,极端情况发生时效率很低。因此我们使用随机选择轴的方法。方法是先随机选择一个下标,然后将该下标元素与左端点元素进行交换,再以左端点元素作为轴排序。

堆排序

使用容量为 k 的小顶堆。元素个数小于 k 的时候,直接放进去,元素个数大于 k 的时候,小于等于堆顶元素,就扔掉,大于堆顶元素,就替换,最后堆顶中的元素就是堆中最小的,整个数组中的第 k 大元素。

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        import heapq
        heap = []
        for i in range(k):
            heapq.heappush(heap, nums[i])
        for j in range(k, len(nums)):
            if nums[j] > heap[0]:
                heapq.heapreplace(heap, nums[j])
        return heap[0]

直接用库了。headq默认是最小堆,heaprepalce() 函数的用法是删除堆中最小元素并加入一个元素。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值