""" 先按照构建顺序将数组元素构建成一颗完全二叉树【层次排放】 从第一个非叶子结点为根节点的子树开始,将其调整为大根堆 调整倒数第二个非叶子结点作为根节点的子树 调整倒数第三个非叶子结点作为根节点的子树 调整完成之后在删除堆顶元素(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)
每日一道Leetcode - 215. 数组中的第K个最大元素 【构建大顶堆】
原文作者:奋进的杰西
原文地址: https://blog.csdn.net/weixin_41041275/article/details/115443185
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/weixin_41041275/article/details/115443185
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。