原题
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
题目:
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
My Solution
方案一(超时)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
res = head = ListNode(-1)
output = []
if not lists:
return output
if len(lists) == 1:
return lists[0]
mark_null = 0
mark_continue_null = 0
while mark_null < len(lists):
min_count = None
for sublist_index in range(len(lists)):
if lists[sublist_index]:
mark_continue_null = 1
if min_count is None:
min_count = lists[sublist_index].val
if lists[sublist_index].val <= min_count:
min_count = lists[sublist_index].val
min_sublist_index = sublist_index
else:
mark_null += 1
# mark_continue_null *= 1
if min_count is None:
return output
res.next = ListNode(min_count)
output.append(min_count)
# res.next = None
res = res.next
mark_null = 0
if mark_continue_null == 1:
lists[min_sublist_index] = lists[min_sublist_index].next
else:
pass
return head.next
方案二(超时)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
if not lists:
return []
if len(lists) == 1:
return lists[0]
amount = len(lists)
# interval = 1
mark_null = 0
# while mark_null < amount - 1:
for i in range(1, amount):
lists[0] = self.merge2Lists(lists[0], lists[i])
return lists[0]
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 = l2.next
point = point.next
if not l1:
point.next = l2
else:
point.next = l1
return head.next
Reference solution
思路分析:
思路一 :
这里是 k 个有序链表 ,小詹看到第一反应是直接递归使用前边合并两个有序链表的思路 ,对 ,完全没毛病的 。然后参考答案里是类似的 ,只不过合并的方式不一样 ,这里采取的是两两合并的方式 ,过程见下图 :
注:自己的方法就是合并效率太低,参考答案采用了两两合并,再下一轮两两合并,类似归并排序的思想,效率大幅提升。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
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 = l2.next
point = point.next
if not l1:
point.next = l2
else:
point.next = l1
return head.next
这种方式的结果大概是 beat 65% 左右。
思路二:
还有一种看起来比较复杂的办法 ,但是结果却很赞 。大体思路分为三步 :
-
创建一个列表
-
将所有链表的元素值 append 进列表
-
进行排序 ,之后再转换为链表结构
代码实现如下 :
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
# 创建一个列表
self.nodes = []
head = point = ListNode(0)
# 将所有链表的节点元素append进列表
for l in lists:
while l:
self.nodes.append(l.val)
l = l.next
for x in sorted(self.nodes):
point.next = ListNode(x)
point = point.next
return head.next
反思:
- 不同的归并方式效率差别极大,尽可能设计采用归并排序的思想,同步进行两两合并,不要range每轮只合并一次;
- 本题依旧是链表类问题,用python做模拟链表很不方便,还是转成C语言来写好了;
- 题目中明确说明
:type lists: List[ListNode] :rtype: ListNode
,即列表中的元素为ListNode类型;返回类型也必须为ListNode类型;自己总是尝试着直接用链表进行操作,答案没错,不过跟出题思路已经偏差了,还是改C语言好了。 - 注意要学会熟练运用高效的归并排序思想:
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