合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
分析:
我想是k次归并。时间复杂度是(k-1)nlogn。
参考的思路是:
题目分析:本题首先将每个链表的首元素取出,构建一个最小堆。堆顶则为最小的元素,用最小元素所在的那个链表的第二个元素替换掉它的位置。然后维护最小堆的特性,再取出堆顶元素,……,一直到所有链表元素都取出为止。
时间复杂度分析:一共是K个链表,假设每个链表有n个元素,首先是K个链表首元素的建堆,花费O(K),然后取堆顶元素,用下一个元素替换掉它,维护最小堆的特性,花费O(lgK),共有K*n个元素,所以花费(K*n-1)*lgK的时间,故总时间为O(K*n*lgK)
我们用优先队列来实现,优先队列的底层是用堆实现的。所谓优先,指的是队列里的元素按照优先级大小排列,优先级大的排在前面,优先级相同的按照入队的顺序排列。首先将每个链表的首元素入队,将最小元素置于堆顶,然后找最小元素所在链表的下一个元素入队,一直到队为空。
from queue import PriorityQueue
# from heapq import heappush,heappop
class Solution(object):
def mergeKLists(self, lists):
dummy = curr = ListNode(None)
q = PriorityQueue()
for idx,node in enumerate(lists):
# 我的妈,链表竟然可以这样遍历
# print(idx,node) # TypeError: 'ListNode' object is not iterable
# 不可以这样遍历- -
if node:
q.put((node.val,idx,node))
# print(q.get()) # (1, 0, <__main__.ListNode object at 0x105d20518>)
while not q.empty():
# 最小的元素在链表尾部
_,idx,curr.next = q.get()
curr = curr.next
if curr.next:q.put((curr.next.val,idx,curr.next))
return dummy.next
## using minheap
def mergeKLists2(self, lists):
dummy = curr = ListNode(None)
heap = []
for idx, node in enumerate(lists):
if node:
heappush(heap, (node.val, idx, node))
while heap:
_, idx, curr.next = heappop(heap)
curr = curr.next
if curr.next:
heappush(heap, (curr.next.val, idx, curr.next))
return dummy.next
详细用法:Python堆和优先队列的使用
参考:
原文:https://blog.csdn.net/Jaster_wisdom/article/details/81332854