合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
【困难】
【分析】逐一两两合并:((list[0]+list[1])+list[2])+...
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
if len(lists)==0:
return None
res=lists.pop(0)
while len(lists)>0:
res=self.merge2Lst(res,lists.pop(0))
return res
def merge2Lst(self,head1,head2):
res=ListNode(0)
node=res
while head1 and head2:
if head1.val>head2.val:
node.next=ListNode(head2.val)
head2=head2.next
else:
node.next=ListNode(head1.val)
head1=head1.next
node=node.next
node.next=head1 if head1 else head2
return res.next
时间超出限制,时间复杂度是 O ( k N ) O(kN) O(kN).
【分析】分治法:两两合并。(list[0]+list[1])+(list[2]+list[3])+...
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
if len(lists)==0:
return None
while len(lists)>1:
lists.append(self.merge2Lst(lists.pop(0),lists.pop(0)))
return lists[0]
def merge2Lst(self,head1,head2):
res=ListNode(0)
node=res
while head1 and head2:
if head1.val>head2.val:
node.next=ListNode(head2.val)
head2=head2.next
else:
node.next=ListNode(head1.val)
head1=head1.next
node=node.next
node.next=head1 if head1 else head2
return res.next
时间复杂付
O
(
N
l
o
g
k
)
O(Nlogk)
O(Nlogk)
【分析】利用优先队列:最高优先级的先出来。举个栗子:
lists= [
0->4->5,
1->3->4,
2->6
]
- 利用优先队列取出list[0],list[1],…,list[k-1]中的头节点,加入到优先队列中。栗子中是0,1,2被拿出来放到了优先队列里面。
- 然后在优先队列中,弹出最小的那个放到答案中,同时这个将弹出来的这个节点的next又加入优先队列。栗子中,0会被答案征用,然后4会被拿出来放到优先队列里,此时优先队列(按照先进先出原则和优先级的原则)的值为1,2,4。
通俗一点,也就是说,只要这k个链表还有节点弹出来,那么每次就会比较这k个节点的val(通过优先队列实现,时间更短,而不是单纯的比较),有哪个链表的节点被答案征用了,那么这个链表就会从再次弹出节点来与其他链表的头节点来做比较,直到所有链表的头节点都被比较完为止。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
from Queue import PriorityQueue
class Solution(object):
def mergeKLists(self, lists):
res=ListNode(0)
node=res
p_queue=PriorityQueue()
for head in lists:
if head:
p_queue.put((head.val,head))
while not p_queue.empty():
val,head=p_queue.get()
node.next=ListNode(val)
if head.next:
p_queue.put((head.next.val,head.next))
node=node.next
return res.next
注: python的优先队列是值小的先出来,如果要限制它从大到小出来,可以乘以-1.
注:测试用例。
# 输入:
# [
# 1->4->5,
# 1->3->4,
# 2->6
# ]
# 输出: 1->1->2->3->4->4->5->6
##生成节点
def createListNode(lst):
head=ListNode(lst.pop(0))
node=head
while lst:
node.next=ListNode(lst.pop(0))
node=node.next
return head
l1,l2,l3=[1,4,5],[1,3,4],[2,6]
lists=[createListNode(l1),createListNode(l2),createListNode(l3)]