合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
题目要求合并给定的K个排序链表,K = 0,1, …, n,且每个链表中的元素可能有重复值。
- 暴力法:首先遍历K个链表的每个结点,同时使用数组存储结点的值。然后将数组中的元素进行排序,最后使用排序后的数组构建结果链表。但这样的方法时间复杂度为 O ( k n ) + O ( n log n ) + O ( k n ) O(kn) + O(n \log n) + O(kn) O(kn)+O(nlogn)+O(kn),效率太低。
class Solution(object):
def mergeKLists(self, lists):
if lists == []: return []
r = []
for l in lists:
cur = l
while cur:
r.append(cur.val)
cur = cur.next
r = sorted(r)
newHead = ListNode(-1)
cur = newHead
for i in r:
cur.next = ListNode(i)
cur = cur.next
return newHead.next
- 两两合并法:K个链表的合并和看成其两两合并后,使用前一个合并后的结果再和下一个链表合并,直到合并为K个链表。时间复杂度为 O ( k N ) O(kN) O(kN),效率依然不高。
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
def merge(head1, head2):
t = ListNode(-1)
head = t
while head1 and head2:
if head1.val <= head2.val:
head.next = ListNode(head1.val)
head1 = head1.next
else:
head.next = ListNode(head2.val)
head2 = head2.next
head = head.next
if head1: head.next = head1
if head2: head.next = head2
return t.next
if len(lists) == 0: return []
if len(lists) == 1: return lists[0]
newHead = None
for i in range(0, len(lists) - 1):
newHead = merge(newHead, lists[i])
return newHead
一个比较优的做法是官方解答中给出的分治法:
-
将k个链表配对并将同一对中的链表合并
-
第一轮合并后,K个链表被合并成 k 2 \frac{k}{2} 2k个链表,然后继续前一步分操作,直到得到最终的链表
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
amount = len(lists)
interval = 1
while interval < amount:
for i in range(0, amount - interval, interval * 2):
lists[i] = self.merge2Lists(lists[i], lists[i + interval])
interval *= 2
return lists[0] if amount > 0 else lists
def merge2Lists(self, l1, l2):
head = point = ListNode(0)
while l1 and l2:
if l1.val <= l2.val:
point.next = l1
l1 = l1.next
else:
point.next = l2
l2 = l1
l1 = point.next.next
point = point.next
if not l1:
point.next=l2
else:
point.next=l1
return head.next