问题:-合并k个排序列表。
我想使用min heap解决这个问题,它可以在python中使用heapq模块实现。下面是函数的示例代码…
heapq.heappush(listwithoutNone,(node.val, node))
但问题是python解释器引发了一个错误:
类型错误:'
所以,我想使用node. val作为minheap节点元素,因为我传递的是一个元组,所以我应该在代码中做什么更改,以便minheap使用node.val堆。
提前感谢。
比较元组时,会比较它们的第一个元素,然后使用它们的第二个元素、它们的元素等打破任何联系。例如,(2,"a")
在这里,您将(node. val,node)
元组插入到堆中,堆会尝试比较它们。如果节点值有平局,它会移动到元组的第二个元素-节点本身。这些只是ListNode
实例。Python不知道如何比较两个ListNodes
,因此出错。
要在ListNodes
之间启用比较,您需要实现丰富的比较方法。一个快速的方法是简单地实现ListNode。__lt__
,然后使用功能工具。total_ordering
装饰器:
import heapq
from functools import total_ordering
@total_ordering
class ListNode:
def __init__(self, value: float, label: str) -> None:
self.value = value
self.label = label
def __lt__(self, other: 'ListNode'):
return self.value <= other.value
def __str__(self):
return f"ListNode(label={self.label}, value={self.value})"
nodes = []
a = ListNode(5, "A")
b = ListNode(3, "B")
c = ListNode(5, "C")
heapq.heappush(nodes, a)
heapq.heappush(nodes, b)
heapq.heappush(nodes, c)
while nodes:
x = heapq.heappop(nodes)
print(x)
这里我们说比较两个ListNode
对象和仅仅比较它们的值是一样的。定义了比较,你甚至根本不需要插入元组。你可以直接插入ListNode
对象,并依赖比较方法。
我想你说的是这个:Leetcode合并k排序列表
我为您分享一个工作解决方案:
head = curr = ListNode(0) # Creating a dummy node
lst = []
for l in lists:
if l:
# Here we need to first push val so that heap can know which is minimum and which is maximum.
# If we insert directly node then heap can't work proper way (in this case heapq.heappop doesn't return minimum node).
lst.append((l.val,l))
heapq.heapify(lst)
while lst:
val,node = heapq.heappop(lst)
curr.next = node
curr = curr.next
node = node.next
if node:
heapq.heappush(lst,(node.val,node))
return head.next
为了改进Saurabh的答案,您可以在迭代各个列表时生成最终的排序列表。
这个想法是首先用每个排序数组的第一个元素填充堆,并用元素来自的数组标记,每当从堆中弹出时,添加与刚刚从堆中弹出的元素关联的数组的下一个元素。
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
heap = []
for i, l in enumerate(lists):
if l is None:
continue
heapq.heappush(heap, (l.val,i))
lists[i] = lists[i].next
out = ListNode() # dummy
cur = out
while heap:
val, i = heapq.heappop(heap)
cur.next = ListNode(val)
cur = cur.next
if lists[i] is not None:
heapq.heappush(heap, (lists[i].val, i))
lists[i] = lists[i].next
return out.next
这也可以修改,以便堆跟踪实际节点,这样就不会创建新节点(除了虚拟头):
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
heap = []
for i, l in enumerate(lists):
if l is None:
continue
heapq.heappush(heap, (l.val, i, l))
lists[i] = lists[i].next
out = ListNode() # dummy
cur = out
while heap:
val, i, node = heapq.heappop(heap)
cur.next = node
cur = cur.next
if lists[i] is not None:
heapq.heappush(heap, (lists[i].val, i, lists[i]))
lists[i] = lists[i].next
return out.next
堆将只包含最大的k
元素,其中k
是进审量列表。因此,我们解决了@Abhishek Jaiswal关于空间复杂度应该是O(k)
的担忧。
编辑:添加空间复杂度改进分析