最近想学一些数据结构,接下来就让我们通过AI刷题来整理学一下Heapq吧!
堆中某个节点的值总是不大于或不小于其父节点的值。
因此,它的根节点一定是最大值或者最小值。
Python heapq模块
Python提供了heapq模块,有利于我们更好的对堆的相关操作进行简化。
我们首先来学一下基本操作:
- 引入库
import heapq
- 堆的建立
- 通过列表建立堆:
a =list()
heapq.heapify(a)
- 通过heappush为堆添加元素
heapq.heappush(a,18)
- 从堆中弹出并返回最小的值
heapq.heappop(a)
- heappushpop(heap,item)
heapq.heappushpop()是heappush和haeppop的结合
先进行heappush(),再进行heappop() - heapreplace(heap.item)
heapreplace(heap.item)弹出并返回 heap 中最小的一项,同时添加新的值
它与heapq.heappushpop()相反,先进行heappop(),再进行heappush() - 获取列表中最大、最小的几个值
利用nlargest(n , iterbale, key=None) 和nsmallest(n , iterbale, key=None)获取列表中最大、最小的几个值
其中,key的作用和sorted( )方法里面的key类似
好了,我们现在已经知道了Python heapq的特点和基本操作,接下来让我们来做这道题目练习一下吧!!!!
先来读题:
小S正在处理一个包含N个整数的数组A,这些整数的编号从0到N-1。他需要通过一系列迭代操作将数组清空。在每次迭代中,小S必须从数组中删除K个值相同的元素,第T次迭代的成本为 T * V,其中V是被删除元素的值。
你的任务是找到清空数组A的最低成本。如果不可能清空数组,则返回-1。
思路:
- 因为迭代成本与次数成正比,因此应当优先先把数组种大的数删除
- 因为每次都是选择符合条件(该值的数量为K的倍数)的最大数,
所以我们选用heapq来做本题,每次弹出数组内现有元素最大值
AC Code:
from collections import Counter
import heapq
def solution(N: int, K: int, A: list) -> int:
# 统计每个元素的出现次数
count = Counter(A)
# 检查是否存在某个元素的出现次数小于K
for value in count.values():
if value%K !=0:
return -1
# 初始化优先队列(最小堆)
min_heap = []
for value, freq in count.items():
# 将每个元素的出现次数和值放入堆中
heapq.heappush(min_heap, (-value,freq))
# 初始化总成本
total_cost = 0
iteration = 1
# 当堆不为空时,继续迭代
while min_heap:
# 取出当前最小频率的元素
value,freq = heapq.heappop(min_heap)
print(freq, value)
# 计算当前迭代的成本
value=-value
cost = iteration * value
total_cost += cost
# 更新剩余元素的出现次数
remaining_freq = freq - K
if remaining_freq > 0:
heapq.heappush(min_heap, (-value,remaining_freq))
# 增加迭代次数
iteration += 1
print(total_cost)
return total_cost
if __name__ == '__main__':
print(solution(N = 6, K = 2, A = [1, 6, 6, 1, 1, 1]) == 11)
print(solution(N = 4, K = 2, A = [5, 5, 5, 5]) == 15)
print(solution(N = 7, K = 1, A = [3,15,12,15,16,11,10]) == 275)
其中,由于Python自带的heapq为最小堆,为实现最大堆,将元素值取负数