合并 k 个已排序的链表并将其作为一个已排序的链表返回。
最古老的方法,依次遍历数组里的链表合并再放回数组里,面试这么写必死无疑。
解题思路:
方法一:分治递归法
用二分法把列表进行拆分成2个2个一组,然后合并每一组链表后再重复操作。
时间复杂度是log(k)*n,n是单个链表的长度。
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def mergeKLists(self , lists ):
# write code here
if len(lists) <= 2:
return self.merge2lists(lists)
def split_lists(lists):
index = len(lists)//2
return lists[:index] , lists[index:]
a,b = split_lists(lists)
a_merge = self.mergeKLists(a)
b_merge = self.mergeKLists(b)
return self.merge2lists([a_merge,b_merge])
def merge2lists(self,lists):
if not lists:
return None
if len(lists) == 1:
return lists[0]
head1,head2 = lists
dump = head = ListNode(0)
while head1 and head2:
if head1.val <= head2.val:
dump.next = head1
head1 = head1.next
else:
dump.next = head2
head2 = head2.next
dump = dump.next #dump也要往后移一位
if head1:
dump.next = head1
elif head2:
dump.next = head2
return head.next
方法二:优先队列法,利用最小堆
用一个大小为K的最小堆(用优先队列+自定义降序实现)(优先队列就是大顶堆,对头元素最大,自定义为降序后,就变成了最小堆,对头元素最小),先把k个链表的头结点放入堆中,每次取堆顶元素,然后将堆顶元素所在链表的下一节点加入堆中。
def mergeKlists2(self,lists): #利用最小堆
import heapq
dump = ListNode(0)
p = dump
head = []
for i in range(len(lists)):
#堆里只有列表中每一个链表的一个元素(最多一个元素,也有可能没有元素)
if lists[i]: #这个列表可能会没有元素
heapq.heappush(head,(lists[i].val,i))
lists[i] = lists[i].next
while head:
val,index = heapq.heappop(head) #取堆顶元素
p.next = ListNode(val)
p = p.next
if lists[index]:
heapq.heappush(head,(lists[index].val,index))
#将堆顶元素下一节点放入堆中
lists[index] = lists[index].next
return dump.next