python堆结构heapq

堆是一种二叉树结构,python中的堆是小根堆。每个父节点的值都小于或等于它的任何子节点;即对于任何一个结点 k k k,都满足:

a[k] <= a[2*k+1] 
a[k] <= a[2*k+2] 

最小的元素总是根元素。

heapq模块是通过堆实现的优先队列算法

方法功能
heapq.heappush(heap, item)将 item 的值加入heap中,保持堆的性质。
heapq.heappop(heap)弹出并返回heap的最小的元素,保持堆的性质。如果堆为空,抛出 IndexError。 heap[0] 访问最小的元素而不弹出它
heapq.heappushpop(heap, item)将item放入堆中,弹出并返回heap的最小元素
heapq.heapify(x)将list x 转换成堆,原地,线性时间内。
heapq.heapreplace(heap, item)弹出并返回 heap 中最小的一项,同时推入新的 item。 堆的大小不变。 如果堆为空则引发 IndexError
heapq.merge(*iterables, key=None, reverse=False)将多个已排序的输入合并为一个已排序的输出。 返回已排序值的 iterator
heapq.nlargest(n, iterable, key=None)从iterable 所定义的数据集中返回前n个最大元素组成的列表
heapq.nsmallest(n, iterable, key=None)从 iterable 所定义的数据集中返回前 n 个最小元素组成的列表

插入删除元素

从堆中插入或者删除元素,元素可以是元组(比较大小根据是元组中的第一个数)

import heapq

h = []
heapq.heappush(h, (5, 'write code'))
# 插入元素
heapq.heappush(h, (7, 'release product'))
heapq.heappush(h, (1, 'write spec'))
heapq.heappush(h, (3, 'create tests'))
heapq.heappop(h)
# 删除根结点
print(h)

[(3, 'create tests'), (7, 'release product'), (5, 'write code')]

用于排序

堆排序可以通过将所有值压入堆中,然后每次取出最小值来实现:

import heapq


def heapsort(iterable):
    h = []
    for value in iterable:
        heapq.heappush(h, value)
    return [heapq.heappop(h) for _ in range(len(h))]


res = heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])
print(res)

以上翻译自:https://docs.python.org/3/library/heapq.html

应用

leetcode 659. 分割数组为连续子序列

在这里插入图片描述

对于示例1,[1,2,3,3,4,5],遍历元素,假设是x,将元素插入到长度最短并且以x-1结尾的列表中,如果没有,则单独作为列表插入。最后判断是否所有的列表是否都大于等于3或者为空。

插入1
[[1]
插入2
[[1,2]]
插入3
[[1,2,3]]
插入3
[[1,2,3],[3]]
插入4,插入到以3结尾,并且长度最短的列表中
[[1,2,3],[3,4]]
插入5
[[1,2,3],[3,45]]
结束,符合要求

这里并不需要真正使用列表,执行插入操作,因为知道以什么结尾,长度是多少,就等于知道了这个列表长啥样。

关键在于如何找到以x-1结尾,并且长度最短的列表。

将以x-1结尾的所有列表的长度,存成一个堆,每次pop最小的长度

插入x 等价于,以x结尾的长度堆,插入一个新的长度;

对应代码如下:

class Solution:
    def isPossible(self, nums) -> bool:
        mp = collections.defaultdict(list)
        # key 最后一个值
        # value 对应的长度,list
        for x in nums:
            queue = mp.get(x - 1)
            # 找出以x-1结尾的子序列的长度list
            if queue:
                prevLength = heapq.heappop(queue)
                # 找出以x-1结尾的子序列的最小长度
                heapq.heappush(mp[x], prevLength + 1)
            else:
                heapq.heappush(mp[x], 1)
        # queue[0] 长度最短的是否小于3
        return not any(queue and queue[0] < 3 for queue in mp.values())
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值