一.问题描述
You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.
Merge all the linked-lists into one sorted linked-list and return it.
Example 1:
Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
1->4->5,
1->3->4,
2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6
Example 2:
Input: lists = []
Output: []
Example 3:
Input: lists = [[]]
Output: []
Constraints:
k == lists.length0 <= k <= 10^40 <= lists[i].length <= 500-10^4 <= lists[i][j] <= 10^4lists[i]is sorted in ascending order.- The sum of
lists[i].lengthwon't exceed10^4.
二.解题思路
这道题的解决方法可能比较多,根据实现的不同主要讲3种。
<1>
拿到题目,很容易想到的一个解法就是迭代lists种每个链表的第一个元素,然后比较它们的大小,把最小的加入到结果变量中,然后将所取的最小元素的那个链表的头指向下一个位置,重复。
时间复杂度 O(MN),M为lists的长度,N为所有链表的元素总数。
<2>优先队列
思路和上面类似,但是此时我们用一个优先队列来储存所有链表的第一个元素,使得这个队列的头永远是最小值,即每次pop出来的链表,它的第一个元素的值是最小的。维护这样一个数据结构(二叉小顶堆实现),每次调整需要 O(logN),一个M次,因此整个的时间复杂度: O(N*log(M))。
<3>分治法,divide and conquer
将lists切分为两等份,即左半部和右半部分,合并左右两部分处理的结果链表来得到最后结果。迭代一直切分,直到最小的分治单位2。
换个思路,从下往上理解就是,首先两两合并lists中的链表,比如第一和第二个链表合并,然后保存到临时变量中,第三和第四个链表合并,保存到临时变量中。迭代完一次后,
判断该临时变量是否长度为1,不为1就按照上述步骤继续两两合并。
时间复杂度:每一次要合并N个数,一共log(M)次,O(N*log(M))
PS:以下内容可不看,同样的方法,下面的实现可能不易于理解。
不开新的临时变量也可以,就需要在迭代的时候动动手脚,
步长指的是迭代的时候,每隔多少取一个元素。
首先设置步长为2,然后每2个一组合并,即i与i+步长/2的两个链表合并,结果保存就保存到lists[i],即与相应位置的链表替换。然后跳到下一个位置j=i+步长/2,直至遍历完一次lists。
然后步长*2,和上述一样操作,直至步长超过lists的长度。
主要需要理解的一个地方就是,lists的长度可能不是被步长整除啊,会不会漏掉呢,
其实不会,假设当前最后一个链表无法被当前步长覆盖(即合并),在下一个步长的时候,它一定会被覆盖掉。
可以自己理解以下,比如 1,2,3,4,5. 首先步长为2,就是1,3合并,然后5的信息漏了,到步长为4的时候,就到1,5合并了。
具体需要看代码,注意边界问题。
三. 源码
注:
方法二代码来自:方法二
方法三易于理解版来自: 方法三易于理解版
# 方法<1>
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
lists=[l for l in lists if l]
if not lists:
return None
ln=ListNode()
head=ln
while lists:
ln.next=ListNode()
ln=ln.next
min_cur=10**4+1
min_idx=-1
for i,l in enumerate(lists):
if l.val<min_cur:
min_idx=i
min_cur=l.val
ln.val=min_cur
lists[min_idx]=lists[min_idx].next
if lists[min_idx]==None:
del lists[min_idx]
return head.next
# 方法<2>
import heapq
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
heap = [(node.val, idx, node) for idx, node in enumerate(lists) if node]
heapq.heapify(heap)
pre_head = ListNode()
node = pre_head
while heap:
_, idx, popped_node = heapq.heappop(heap)
if popped_node.next:
heapq.heappush(heap, (popped_node.next.val, idx, popped_node.next))
node.next = popped_node
node = node.next
return pre_head.next
# 方法<3> 易于理解版
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if not lists:
return None
while len(lists)>1:
A = lists.pop(0)
B = lists.pop(0)
head =ListNode(0)
temp = head
while A and B:
if A.val<=B.val:
temp.next = A
A = A.next
else:
temp.next = B
B = B.next
temp = temp.next
temp.next = A or B
lists.append(head.next)
return lists[0]
# 方法<3>, 直接lists上操作
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
def mergeTwoLists(l1,l2):
cur=ListNode()
head=cur
while l1 and l2:
if l1.val < l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur=cur.next
if l1:
cur.next = l1
if l2:
cur.next = l2
return head.next
lists=[l for l in lists if l]
if not lists:return None
l=len(lists)
interval=1
while interval<l:
for i in range(0,l-interval,2*interval):
lists[i]=mergeTwoLists(lists[i],lists[i+interval])
interval*=2
return lists[0]
1477

被折叠的 条评论
为什么被折叠?



