题目描述
方法—最小堆
合并后的第一个节点 first,一定是某个链表的头节点(因为链表已按升序排列);
合并后的第二个节点,可能是某个链表的头节点,也可能是 first 的下一个节点;
按照这个过程进行下去,每当我们找到一个节点值最小的节点 x,就把节点 x.next 加入「可能是最小节点」的集合中,让x.next和上一轮剩下的待选节点重新进行比较,选出新的节点加入到新链表中;
因此,我们需要一个数据结构,它支持:①从数据结构中找到并移除最小节点,
②插入节点。
拓展
堆栈
满足上述功能的一个数据结构———>最小堆
初始把所有链表的头节点入堆,然后不断弹出堆中最小节点 x,如果 x.next 不为空就加入堆中。循环直到堆为空。把弹出的节点按顺序拼接起来。
堆的性质:
一种近似的完全二叉树,先选一个父节点放在最上面,然后向下分两个叉作为子节点,每个子节点同时又是下一棵子树的父节点,向下再分两个叉;
它满足:每个子结点的值都小于父节点的值,
这样,树从上到下的节点值逐层减小,最后一层是最小值所在的位置。
本例用到的一个魔方方法—>给类动态地添加一个方法(功能)
name.__lt__:#冒号后写具体功能
python标准库heapq的几个函数
heapify()#()内是可迭代对象,heapify()将这个对象堆话,使其具有堆的性质;不返回任何的东西,直接修改堆
heappop() #弹出最小元素(对最小堆)(弹出后从堆中删除删除)
heappush() #向堆中加入元素
实现
ListNode.__lt__ = lambda a, b: a.val < b.val #__lt__魔方方法,使类具有比较大小的功能
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
cur = dummy = ListNode(None) #哨兵节点初始化为空
h = [head for head in lists if head] #将列表的头结点压入栈
heapify(h) #堆化
while h : #当堆不为空时
node = heappop(h) #node是堆的最小值
if node.next:
heappush(h,node.next) #将node的下一个节点压入栈,和上一轮的入栈元素比较,选出新的node
cur.next = node #合并到新链表
cur = cur.next #准备合并下一个节点
return dummy.next #返回结果