选择排序之--堆排序

https://leetcode-cn.com/submissions/detail/24096354/

 

 

  

class Solution(object):
    def sortArray(self, nums): 
# ------------------------------------------------------------------------  
                                      # sift时间复杂度:树的高度--logn
        def sift(data, length, dad):  # dad为要调整的节点
            # 选出左右孩子中较大者,去跟父节点i比较
            large = 2*dad + 1           # large先指向dad的左孩子
            while large < length:   
                if large+1 < length and data[large] < data[large+1]:
                    large += 1      # 如果右孩子比左孩子大,则large指向右孩子
                
                if data[dad] >= data[large]:
                    break           # 如果父节点dad较大,则退出,就不用调整了
                    
                else:               # 否则,dad退位,换较大的孩子为新的父节点   
                    data[dad],data[large] = data[large],data[dad]
                    dad = large       # large位置的堆状态可能被破坏,继续调整
                    large = 2*dad + 1 # large为dad的左孩子
                                
        def heapSort(data):          # 堆排序时间复杂度:O(nlogn),空间复杂度:O(1) 
            if not data: return None
            length = len(data)
            for i in range(length//2-1, -1, -1): # n/2-1:最后一个非叶子节点开始调整
                sift(data, length, i)  
          
            for i in range(length-1, 0, -1):    # n-1:最后一个节点开始排序
                # 堆排序:最值下降
                data[0], data[i] = data[i], data[0] # 0位置数依次与无序的最后一个数交换。
                # 调整堆:最值上升
                sift(data, i, 0)  # 0位置被交换后,堆状态被破坏,需调整0
            return data  
# ------------------------------------------------------------------------          
        return heapSort(nums)
        

排序类别

排序方法

时间复杂度

空间复杂度

稳定性

复杂性

平均情况

最坏情况

最好情况

选择排序

堆排序

O(nlog2n)

O(nlog2n)

O(nlog2n)

O(1)

不稳定

较复杂

堆排应用:数组中第/前k个最大元素

https://leetcode-cn.com/submissions/detail/24096467/

class Solution(object):
    # 数组中的第k个最大元素--topK问题
# ------------------------------------------------------------------------ 
    def findKthLargest(self, nums, k):
        # 调整成小顶堆,O(logn)
        def sift(data, length, dad):
            large = 2 * dad + 1
            while large < length:
                if large + 1 < length and data[large] > data[large + 1]:
                    large += 1
                if data[dad] <= data[large]: break
                data[dad], data[large] = data[large], data[dad]
                dad = large
                large = 2 * dad + 1
        
        for i in range(k // 2 - 1, -1, -1): # 维持一个k个元素的小顶堆
            sift(nums, k, i)  
        for j in range(k, len(nums)):       # 从第k+1个元素开始遍历到结束 
            if nums[j] < nums[0]:           # 小于堆顶,必定小于整个堆内元素
                continue                    # 故不在前k个最大元素中,跳过
            else:
                nums[0] = nums[j]           # 遇到>堆顶元素,则替换堆顶
                sift(nums, k, 0)            # 调整堆顶
        return min(nums[:k])  
# ------------------------------------------------------------------------ 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值