当涉及到合并K个排序链表时,通常有两种主要的方法:使用堆(优先队列)或者直接合并后排序。这两种方法各有优劣,我将简要介绍它们。
使用堆(优先队列)
这种方法利用堆来维护所有链表当前最小的元素。具体步骤如下:
- 将每个链表的头结点加入最小堆中。
- 每次从堆中取出最小元素,将其加入结果链表,并将该元素所在链表的下一个节点加入堆中。
- 重复上述步骤直到堆为空。
-
python代码
-
ListNode.__lt__ = lambda a, b: a.val<b.val class Solution: def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]: cur = dummy = ListNode() head_list = [head for head in lists if head] heapify(head_list) while head_list: pop = heappop(head_list) if pop.next: heappush(head_list, pop.next) cur.next = ListNode(pop.val) cur = cur.next return dummy.next
这种方法的时间复杂度为O(NlogK),其中N是所有链表节点的总数,K是链表的个数。
补充
heapify(list)堆化
heappop(heap)出堆 排出最小值并返回排出值
heappush(heap, val)入堆
若list中为不可比较的对象如ListNode, 在对象中定义__lt__方法给出判断依据
如:
ListNode.__lt__ = lambda a, b : a.val < b.val
直接合并后排序
另一种方法是将所有链表的节点值存入数组中,然后对数组进行排序,最后根据排好序的数组构建新的链表。具体步骤如下:
- 将所有链表的节点值存入数组中。
- 对数组进行排序。
- 根据排好序的数组构建新的链表。
-
python代码
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
vals = []
for i in lists:
pcur = i
while pcur:
vals.append(pcur.val)
pcur = pcur.next
vals.sort()
phead = ListNode(0)
pcur = phead
for i in vals:
pcur.next = ListNode(i)
pcur = pcur.next
return phead.next
这种方法的时间复杂度为O(NlogN),其中N是所有链表节点的总数。虽然简单,但在节点数较大时效率较低。
在实际应用中,如果K较小或者N较大,通常会选择使用堆的方法,因为它的时间复杂度更优。相反,如果K较大且N也较大,直接合并后排序可能会更简单高效一些。
希望这篇博客能够帮助你更好地理解合并K个排序链表的两种常见解决方法。