Leetcode演算法——23、合併多個連結串列
阿新 • • 發佈:2018-12-17
合併 k 個有序連結串列,返回一個新的有序連結串列。
示例: Input: [ 1->4->5, 1->3->4, 2->6 ] Output: 1->1->2->3->4->4->5->6
思路
維護 k 個指標,每次提取 k 個數中最小的數,然後此指標+1,繼續迴圈。
使用了優先佇列(最小堆),每次提取最小數的複雜度由O(k)變為了O(logk)。
整體時間複雜度為O(nlogk)。
python實現
class ListNode:
def __init__(self, x):
if isinstance(x, list):
self.val = x[0]
self.next = None
head = self
for i in range(1, len(x)):
head.next = ListNode(x[i])
head = head.next
else:
self.val = x
self.next = None
def output(self):
'''
輸出連結串列
'''
result = str(self.val)
head = self.next
while(head is not None):
result += f' -> {head.val}'
head = head.next
return '(' + result + ')'
def mergeKLists(lists):
"""
:type lists: list[ListNode]
:rtype: ListNode
歸併排序法
"""
from queue import PriorityQueue
# 初始化結果連結串列
head = ListNode(0)
p = head
# 將每個連結串列的第一個節點放入到堆中
q = PriorityQueue()
for l in lists:
if l:
q.put((l.val, id(l), l))
# 這裡加上id(l)是因為元組比較大小是從左到右,如果l.val相等,則會繼續比較第二個。
# 如果此時第二個是l,則會報錯,因為ListNode之間的大小不知道怎麼比較
# 而id(l)表示l的記憶體地址,int型,且可以保證所有存在物件的id都是不同的。
# 每次從堆中選擇最小節點
while(not q.empty()):
val, _, node = q.get()
p.next = ListNode(val)
p = p.next
node = node.next
if node:
q.put((node.val, id(node), node))
return head.next
if '__main__' == __name__:
lists = []
lists.append(ListNode([1,4,5]))
lists.append(ListNode([1,3,4]))
lists.append(ListNode([2,6]))
print(mergeKLists(lists).output())