合並k個有序鏈表


題目:

合並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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM