給定 k
個遞增排序的鏈表,將它們合併成一個遞增排序的鏈表,並返回合併後的鏈表。
範例 1:
Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]
範例 2:
Input: lists = []
Output: []
範例 3:
Input: lists = [[]]
Output: []
將 k
個排序鏈表合併成一個排序鏈表是經典的合併問題,可以考慮以下幾種解法:
k
個鏈表分成兩半,遞歸合併。思路
程式碼
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
nodes = []
# 收集所有節點的值
for l in lists:
while l:
nodes.append(l.val)
l = l.next
# 排序節點
nodes.sort()
# 根據排序結果重新構建鏈表
dummy = ListNode()
current = dummy
for val in nodes:
current.next = ListNode(val)
current = current.next
return dummy.next
時間與空間複雜度
思路
程式碼
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
if not lists:
return None
while len(lists) > 1:
merged_lists = []
# Merge two lists at a time
for i in range(0, len(lists), 2):
l1 = lists[i]
l2 = lists[i + 1] if i + 1 < len(lists) else None
merged_lists.append(self.mergeTwoLists(l1, l2))
lists = merged_lists
return lists[0]
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode()
current = dummy
while l1 and l2:
if l1.val < l2.val:
current.next = l1
l1 = l1.next
else:
current.next = l2
l2 = l2.next
current = current.next
current.next = l1 if l1 else l2
return dummy.next
時間與空間複雜度
思路
程式碼
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
if not lists:
return None
if len(lists) == 1:
return lists[0]
mid = len(lists) // 2
left = self.mergeKLists(lists[:mid])
right = self.mergeKLists(lists[mid:])
return self.mergeTwoLists(left, right)
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode()
current = dummy
while l1 and l2:
if l1.val < l2.val:
current.next = l1
l1 = l1.next
else:
current.next = l2
l2 = l2.next
current = current.next
current.next = l1 if l1 else l2
return dummy.next
時間與空間複雜度
思路
程式碼
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
class HeapNode:
def __init__(self, node):
self.node = node
def __lt__(self, other):
return self.node.val < other.node.val
heap = []
# 初始化堆
for l in lists:
if l:
heapq.heappush(heap, HeapNode(l))
dummy = ListNode()
current = dummy
while heap:
# 取出最小節點
smallest = heapq.heappop(heap).node
current.next = smallest
current = current.next
# 如果還有後繼節點,加入堆中
if smallest.next:
heapq.heappush(heap, HeapNode(smallest.next))
return dummy.next
時間與空間複雜度
對於 k
值較小時,分治法和兩兩合併法都表現不錯;當 k
值較大時,優先隊列法因其高效性表現最佳。