【Leetcode 23】合併K個排序鏈表

題目描述

在這裏插入圖片描述

解題思路

解法一:暴力法

  • 遍歷k個鏈表,將所有節點值保存到列表中
  • 將列表排序
  • 遍歷排序後的列表,創建一個新的有序鏈表

python代碼

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        self.nodes = []
        tmp = head = ListNode(0)
        for i in lists:
            while i:
                self.nodes.append(i.val)
                i = i.next
        for j in sorted(self.nodes):
            head.next = ListNode(j)
            head = head.next
        return tmp.next

運行結果

時間複雜度O(NlogN)O(NlogN),其中 NN是節點的總數目。

  • 遍歷所有的值需花費 O(N)O(N)的時間。
  • 一個穩定的排序算法花費 O(NlogN)O(Nlog N) 的時間。
  • 遍歷同時創建新的有序鏈表花費 O(N)O(N)的時間。

空間複雜度O(N)O(N)

  • 排序花費 O(N)O(N)空間(這取決於你選擇的算法)。
  • 創建一個新的鏈表花費 O(N)O(N) 的空間。
    在這裏插入圖片描述

解法二:分治算法

分治其實就是不斷縮小其規模,再不斷合併擴大的過程
在這裏插入圖片描述
找到中間點,將其一分爲二,再不停的進行拆分,直至到不能再拆分(規模爲1的時候)便返回。
之後開始合併,合併的代碼借用了合併兩個排序鏈表的代碼。
當兩個規模最小的鏈表合併完後,其規模就變大了,然後不斷重複這個合併過程,直到最終得到一個有序的鏈表。

python代碼

 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 = l1
                l1 = point.next.next
            point = point.next
        if not l1:
            point.next=l2
        else:
            point.next=l1
        return head.next 

運行結果

時間複雜度O(Nlogk)O(N\log k) ,其中k是鏈表的數目。

  • 我們可以在O(n)O(n)的時間內合併兩個有序鏈表,其中 n是兩個鏈表中的總節點數。
  • 將所有的合併進程加起來,我們可以得到:在這裏插入圖片描述

空間複雜度:O(1).
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章