每日一道Leetcode - 215. 数组中的第K个最大元素 【构建大顶堆】

《每日一道Leetcode - 215. 数组中的第K个最大元素 【构建大顶堆】》

""" 先按照构建顺序将数组元素构建成一颗完全二叉树【层次排放】 从第一个非叶子结点为根节点的子树开始,将其调整为大根堆 调整倒数第二个非叶子结点作为根节点的子树 调整倒数第三个非叶子结点作为根节点的子树 调整完成之后在删除堆顶元素(k-1次),删除一次将末尾节点到堆顶位置再进行调整 最后返回堆顶元素 时间复杂度O(nlogn) 建堆时间代价为O(n),删除的总代价是O(klogn),k<n,渐进时间复杂度为O(n+klogn) 空间复杂度 O(logn), 递归使用栈空间的空间代价 """
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        # 构建大顶堆
        self.buildMaxHeap(nums)
        # 找第K个 删除k-1次
        for _ in range(k-1):
            # 堆顶和堆尾首尾交换
            nums[0],nums[-1] = nums[-1],nums[0]
            # 弹出堆尾元素
            nums.pop()
            # 从堆头开始调整
            self.adjust_max_heap(nums,0)
        return nums[0]

    def buildMaxHeap(self,nums):
        # 从后往前遍历 即从第一个非叶子结点为根节点的子树开始调整大顶堆
        for in_node in range(len(nums)//2-1,-1,-1):
            # 调整大顶堆
            self.adjust_max_heap(nums,in_node)

    def adjust_max_heap(self,nums,in_node):
        # 从in_node节点开始调整 
        # in_node左节点索引 2*in_node+1 右节点索引 2*in_node+2
        # 假设当前子树最大值索引为in_node
        l,r,large_index = 2*in_node+1,2*in_node+2,in_node
        # 判断左节点和右节点哪个最大,且比当前large_index还要大,替换当前large_index的索引值
        if l<len(nums) and nums[l]>nums[large_index]:
            large_index = l
        if r<len(nums) and nums[r]>nums[large_index]:
            large_index = r
        # 如果large_index索引值变了,就要交换
        if large_index != in_node:
            nums[large_index],nums[in_node] = nums[in_node],nums[large_index]
            # 此时还要从large_index的节点处(原来的左/右节点)继续向下调整堆
            self.adjust_max_heap(nums,large_index)
    原文作者:奋进的杰西
    原文地址: https://blog.csdn.net/weixin_41041275/article/details/115443185
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞