Heapq | 最低成本清空数组 | 豆包MarsCode AI刷题

80 阅读3分钟

最近想学一些数据结构,接下来就让我们通过AI刷题来整理学一下Heapq吧!

堆中某个节点的值总是不大于或不小于其父节点的值。

因此,它的根节点一定是最大值或者最小值。

Python heapq模块

Python提供了heapq模块,有利于我们更好的对堆的相关操作进行简化。
我们首先来学一下基本操作:

  1. 引入库
import heapq
  1. 堆的建立
  • 通过列表建立堆:
a =list()
heapq.heapify(a)
  1. 通过heappush为堆添加元素
heapq.heappush(a,18)
  1. 从堆中弹出并返回最小的值
heapq.heappop(a)
  1. heappushpop(heap,item)
    heapq.heappushpop()是heappush和haeppop的结合
    先进行heappush(),再进行heappop()
  2. heapreplace(heap.item)
    heapreplace(heap.item)弹出并返回 heap 中最小的一项,同时添加新的值
    它与heapq.heappushpop()相反,先进行heappop(),再进行heappush()
  3. 获取列表中最大、最小的几个值
    利用nlargest(n , iterbale, key=None) 和nsmallest(n , iterbale, key=None)获取列表中最大、最小的几个值
    其中,key的作用和sorted( )方法里面的key类似

好了,我们现在已经知道了Python heapq的特点和基本操作,接下来让我们来做这道题目练习一下吧!!!!

先来读题:

小S正在处理一个包含N个整数的数组A,这些整数的编号从0N-1。他需要通过一系列迭代操作将数组清空。在每次迭代中,小S必须从数组中删除K个值相同的元素,第T次迭代的成本为 T * V,其中V是被删除元素的值。

你的任务是找到清空数组A的最低成本。如果不可能清空数组,则返回-1

思路:

  1. 因为迭代成本与次数成正比,因此应当优先先把数组种大的数删除
  2. 因为每次都是选择符合条件(该值的数量为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为最小堆,为实现最大堆,将元素值取负数