题目:
合并k个有序链表,并将结果用一个有序链表输出
例如:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
思路:
假设k个链表的总元素数目为n。首先想到两两合并列表,在序列1和2合并,3和4合并,依次类推。直到合并的只剩一个链表。这种操作的时间复杂度为O(nlog(k)),空间复杂度为O(1)。python代码如下:
classSolution(object):defmergeKLists(self, lists):if notlists:returnNonewhile len(lists) > 1:
tmp_node=self.mergeTwoLists(lists.pop(0), lists.pop(0))
lists.append(tmp_node)returnlists[0]defmergeTwoLists(self, p1, p2):
new_head= ListNode(-1)
tail=new_headwhile p1 is not None and p2 is notNone:if p1.val <=p2.val:
tail.next, tail=p1, p1
p1=p1.nextelse:
tail.next, tail=p2, p2
p2=p2.nextif p1 isNone:
tail.next=p2elif p2 isNone:
tail.next=p1return new_head.next
注意到在mergeTwoLists()中使用了循环进行合并。当节点数量n大于1000时,使用循环合并比较有效。因为python默认限制函数迭代次数为1000,用迭代的方法合并两个链表,节点数多了就会报错。
还可以同时合并所有列表,这中间需要比较这k个链表的头结点哪个最小。直接比较效率低,想到构建辅助数组,用最大堆来帮助比较。这样做的时间复杂度也是O(nlog(k)),空间复杂度为O(k)。同时注意到某些链表合并完后,辅助数组的长度减小,单次查找速度复杂度会小于log(k)。因此这种用最小堆合并的方式速度会比二分合并快一些。实际上在LeetCode23. Merge k Sorted Lists的测试用例上跑的时候,两种方法花的时间分别是165ms,103ms。
importheapqclassSolution(object):defmergeKLists(self, lists):
head= ListNode(-1)
current=head
heap=[]for node inlists:ifnode:
heap.append((node.val, node))
heapq.heapify(heap)whileheap:
_, ref=heapq.heappop(heap)
current.next=ref
current=current.nextifref.next:
heapq.heappush(heap, (ref.next.val, ref.next))return head.next