LeetCode - Merge k Sorted Lists(合併 k 個排序鏈表)
題目描述
給定 k
個排序的鏈表,將它們合併成一個排序鏈表,並返回該排序鏈表的頭節點。
範例:
1
2
3
4
5
6
7
8
9
輸入:lists = [[1,4,5],[1,3,4],[2,6]]
輸出:[1,1,2,3,4,4,5,6]
解釋:所有鏈表合併後變成 [1,1,2,3,4,4,5,6]
輸入:lists = []
輸出:[]
輸入:lists = [[]]
輸出:[]
限制:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i]
已按升序排序lists[i].length
的總和不超過10^4
解法思路
該問題是典型的合併 k 個排序鏈表問題,可以考慮以下幾種方法:
方法一:分治合併
- 使用兩兩合併的方式,首先合併兩個鏈表,再將結果合併至第三個鏈表,如此反覆,直到最終得到一個合併的結果。
- 這種方式類似於合併排序(merge sort),能有效降低合併的時間複雜度。
方法二:使用優先隊列(最小堆)
- 將每個鏈表的頭節點放入最小堆中,最小堆可以維持節點值的排序。
- 每次從堆中取出當前最小的節點,並將該節點的下一個節點(如果有)放入堆中。
- 重複此過程,直到所有節點都被合併完成。
方法二範例代碼
以下是使用最小堆的 Python 實現:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import heapq
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
# 定義比較函數,方便在堆中進行比較
def __lt__(self, other):
return self.val < other.val
def mergeKLists(lists):
# 建立最小堆
min_heap = []
# 將每個鏈表的頭節點加入堆中
for head in lists:
if head:
heapq.heappush(min_heap, head)
# 建立一個虛擬頭節點,方便返回結果
dummy = ListNode()
current = dummy
# 從堆中取出節點並構建結果鏈表
while min_heap:
# 取出最小節點
node = heapq.heappop(min_heap)
current.next = node
current = current.next
# 如果該節點的下一個節點存在,加入堆中
if node.next:
heapq.heappush(min_heap, node.next)
return dummy.next
代碼解析
- 建立最小堆:將所有鏈表的頭節點加入最小堆中,以方便每次取得最小值。
- 構建結果鏈表:從最小堆中彈出節點,連接到結果鏈表,並將該節點的下一個節點(如果存在)加入堆中。
- 返回結果:返回虛擬頭節點的下一個節點,即合併後的鏈表。
時間和空間複雜度
- 時間複雜度:O(N log k),其中
N
是所有節點的總數,k
是鏈表數量。在每次插入和彈出操作中,堆的大小為k
。 - 空間複雜度:O(k),因為堆中最多儲存
k
個節點。
本文章以 CC BY 4.0 授權