1. 程式人生 > >合並k個有序鏈表

合並k個有序鏈表

object 依次 鏈表合並 pen 有序鏈表 node imp sts 空間復雜度

題目:

合並k個有序鏈表,並將結果用一個有序鏈表輸出

例如:
輸入: [ 1->4->5, 1->3->4, 2->6 ] 輸出: 1->1->2->3->4->4->5->6

思路:

假設k個鏈表的總元素數目為n。首先想到兩兩合並列表,在序列1和2合並,3和4合並,依次類推。直到合並的只剩一個鏈表。這種操作的時間復雜度為O(nlog(k)),空間復雜度為O(1)。python代碼如下:

class Solution(object):
    def mergeKLists(self, lists):
        
if not lists: return None while len(lists) > 1: tmp_node = self.mergeTwoLists(lists.pop(0), lists.pop(0)) lists.append(tmp_node) return lists[0] def mergeTwoLists(self, p1, p2): new_head = ListNode(-1) tail = new_head while
p1 is not None and p2 is not None: if p1.val <= p2.val: tail.next, tail = p1, p1 p1 = p1.next else: tail.next, tail = p2, p2 p2 = p2.next if p1 is None: tail.next = p2 elif p2 is None: tail.next
= p1 return new_head.next

註意到在mergeTwoLists()中使用了循環進行合並。當節點數量n大於1000時,使用循環合並比較有效。因為python默認限制函數叠代次數為1000,用叠代的方法合並兩個鏈表,節點數多了就會報錯。

還可以同時合並所有列表,這中間需要比較這k個鏈表的頭結點哪個最小。直接比較效率低,想到構建輔助數組,用最大堆來幫助比較。這樣做的時間復雜度也是O(nlog(k)),空間復雜度為O(k)。同時註意到某些鏈表合並完後,輔助數組的長度減小,單次查找速度復雜度會小於log(k)。因此這種用最小堆合並的方式速度會比二分合並快一些。實際上在LeetCode23. Merge k Sorted Lists的測試用例上跑的時候,兩種方法花的時間分別是165ms,103ms。

import heapq
class Solution(object):
    def mergeKLists(self, lists):
        head = ListNode(-1)
        current = head
        heap = []
        for node in lists:
            if node:
                heap.append((node.val, node))
        heapq.heapify(heap)
        while heap:
            _, ref = heapq.heappop(heap)
            current.next = ref
            current = current.next
            if ref.next:
                heapq.heappush(heap, (ref.next.val, ref.next))
        return head.next

合並k個有序鏈表