算法向 python如何操作堆
堆是一种特别的完全二叉树结构,其中每个父节点的值都小于或等于其所有子节点的值(最小堆),或者每个父节点的值都大于或等于其所有子节点的值(最大堆)。Python 的heapq模块提供了一种实现堆队列(也称为优先队列)的方式。(实现的为最小堆)heapq这个名字,它源自 "heap queue",即“堆队列”。
目录
前言
堆是一种特别的完全二叉树结构,其中每个父节点的值都小于或等于其所有子节点的值(最小堆),或者每个父节点的值都大于或等于其所有子节点的值(最大堆)。
Python 的 heapq
模块提供了一种实现堆队列(也称为优先队列)的方式。(实现的为最小堆)
heapq
这个名字,它源自 "heap queue",即“堆队列”。
各类操作
创建堆
在 heapq
中,堆是用列表来表示的。可以通过以下方式创建一个堆:
import heapq
heap = []
实际上,这同创建列表没有区别,创建的也只是一个普通的列表
heapq
模块通过对这个列表进行特定的操作,使其表现得像一个堆。重点在于,堆的属性(例如,父节点的值小于其子节点的值,这是最小堆的性质)并不是由列表本身的数据结构直接支持,而是由 heapq
模块提供的函数强加的规则。
向堆中添加元素
使用 heapq.heappush(heap, item)
向堆中添加元素,同时保持堆的属性。
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 4)
从堆中弹出最小的元素
使用 heapq.heappop(heap)
从堆中移除并返回最小的元素,同时保持堆的属性。
smallest = heapq.heappop(heap)
查看堆中最小的元素
可以直接访问堆的第一个元素(heap[0]
)来查看最小的元素,而不用弹出它。
smallest = heap[0]
将一个列表转换成堆
使用 heapq.heapify(x)
将列表 x
转换成堆,这个操作可以在 O(n) 时间内完成。
heapq.heapify(my_list)
使用最大堆
heapq
模块只提供了最小堆的实现。如果需要一个最大堆,一种简单的方法是将所有的值取负,这样最小的数在取负后就会变成最大的数。
# 添加元素到最大堆
heapq.heappush(max_heap, -item)
# 从最大堆获取最大元素
max_item = -heapq.heappop(max_heap)
补充说明
- 在 Python 中,使用
heapq
操作的列表会被组织成一个堆结构,但这并不意味着列表中的元素会从左到右线性增大。实际上,堆是一种特殊的树形数据结构,具体来说是一个完全二叉树,它满足某个节点的值不大于(最小堆)或不小于(最大堆)其子节点的值,除了知道第一个元素是最小的,我们不能仅通过观察位置来直接确定列表中元素的排序。。 - 在很多情况下,我们不需要队列的所有元素都完全有序。我们只需要能够快速访问和删除优先级最高的元素。基于堆的优先队列在这方面非常高效,特别是在插入和删除操作上。对于一个含有
n
个元素的堆,插入操作和删除最小元素的操作的时间复杂度都是O(log n)
。相比之下,如果维护一个始终完全有序的列表,插入操作可能需要O(n)
的时间复杂度,因为可能需要移动列表中的多个元素来保持顺序。
相关算法题
题目
假设 力扣(LeetCode)即将开始 IPO 。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k
个不同的项目。帮助 力扣 设计完成最多 k
个不同项目后得到最大总资本的方式。
给你 n
个项目。对于每个项目 i
,它都有一个纯利润 profits[i]
,和启动该项目需要的最小资本 capital[i]
。
最初,你的资本为 w
。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。
总而言之,从给定项目中选择 最多 k
个不同项目的列表,以 最大化最终资本 ,并输出最终可获得的最多资本。
答案保证在 32 位有符号整数范围内。
示例 1:
输入:k = 2, w = 0, profits = [1,2,3], capital = [0,1,1] 输出:4 解释: 由于你的初始资本为 0,你仅可以从 0 号项目开始。 在完成后,你将获得 1 的利润,你的总资本将变为 1。 此时你可以选择开始 1 号或 2 号项目。 由于你最多可以选择两个项目,所以你需要完成 2 号项目以获得最大的资本。 因此,输出最后最大化的资本,为 0 + 1 + 3 = 4。
示例 2:
输入:k = 3, w = 0, profits = [1,2,3], capital = [0,1,2] 输出:6
提示:
1 <= k <= 105
0 <= w <= 109
n == profits.length
n == capital.length
1 <= n <= 105
0 <= profits[i] <= 104
0 <= capital[i] <= 109
解题思路
对于此题,我们使用贪心算法加堆实现,尝试每一步都最大化利润
需要注意的是,zip()函数实质上是把这两个列表(可迭代对象)一一对应打包成了元组
- 对于k次可选次数
- 当projects非空且其第一个元素的投资成本比我们当前总资本小或者相等
- 将这个项目的数据取出来,进行下一步操作,同时这个project也被从projects里pop出来了
- 把这个项目的利润变成负数,加入到我们的“最大堆”(因为此时我们是对利润取负的)
- 这样,我们就筛选出来了所有可以投资的堆
- 如果我们这些可以投资的堆非空,我们就投资最大荔韵的项目,并将利润加给当前的资本
解题代码
class Solution(object):
def findMaximizedCapital(self, k, W, Profits, Capitals):
current_capital = W
projects = sorted(zip(Capitals, Profits), key=lambda x: x[0])
max_heap = []
for _ in range(k):
while projects and projects[0][0] <= current_capital:
capital, profit = heapq.heappop(projects)
heapq.heappush(max_heap, (-profit, capital))
if max_heap:
current_capital += -heapq.heappop(max_heap)[0]
else:
break
return current_capital

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)