1. 程式人生 > >Leetcode演算法——23、合併多個連結串列

Leetcode演算法——23、合併多個連結串列

合併 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())