Surface Pro 7装Kali Linux踩坑全记录:从触摸屏失灵到字体模糊,手把手教你搞定驱动和优化
2026/4/21 18:57:46
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]输出:[1,1,2,3,4,4,5,6]解释:链表数组如下: [ 1->4->5, 1->3->4, 2->6 ] 将它们合并到一个有序链表中得到。 1->1->2->3->4->4->5->6
示例 2:
输入:lists = []输出:[]
示例 3:
输入:lists = [[]]输出:[]
提示:
k == lists.length0 <= k <=![]()
0 <= lists[i].length <= 500
<= lists[i][j] <=![]()
lists[i]按升序排列lists[i].length的总和不超过分治法(Divide and Conquer)的核心是「分而治之」:
该思路的本质是把 “一次面对 K 个链表选最小值” 的高开销操作,转化为 “多次面对 2 个链表选最小值” 的低开销操作,最终将时间复杂度从暴力法的O(Nk)优化到O(N log k)(N 为总节点数,k 为链表数量)。
首先判断输入的链表列表是否为空(if not lists):
None(无链表可合并);调用核心递归函数_merge(lists, left, right),参数left和right表示当前要处理的链表区间(初始为0到len(lists)-1),递归逻辑如下:
left == right时,说明当前区间只剩 1 个链表,无需合并,直接返回该链表(最小子问题的解);mid = (left + right) // 2,将当前区间拆分为左半区(left ~ mid)和右半区(mid+1 ~ right);left_list;right_list;_merge_two_lists将left_list和right_list(两个升序链表)合并为一个升序链表,作为当前区间的合并结果返回。_merge_two_lists(l1, l2)负责解决最基础的 “合并 2 个升序链表” 问题,执行逻辑:
dummy = ListNode(0),用于简化链表拼接(避免处理 “头节点为空” 的边界情况);curr指针指向dummy,同时遍历l1和l2:l1.val和l2.val,将值更小的节点接在curr.next;l1.val < l2.val则l1 = l1.next);curr指针(curr = curr.next),准备接下一个节点;l1或l2有一个遍历完时,将未遍历完的链表直接接在curr.next(因为链表本身是升序的,剩余节点无需再比较);dummy.next(跳过虚拟头节点,得到合并后的真实头节点)。lists = [[1,4,5],[1,3,4],[2,6]]为例)_merge(lists, 0, 2),mid = 1,拆分左区间(0,1)、右区间(2,2);(2,2):终止条件触发,返回[2,6];(0,1):mid=0,拆分左(0,0)(返回[1,4,5])、右(1,1)(返回[1,3,4]),合并这两个链表得到[1,1,3,4,4,5];[1,1,3,4,4,5]和右区间结果[2,6],最终得到[1,1,2,3,4,4,5,6]。//计算mid,避免浮点误差,保证区间拆分对称。O(N log k)O(N)(遍历所有节点);log k(每次拆分区间减半,直到只剩 1 个链表);O(log k)log k(拆分 k 个链表需要log 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): # 边界处理1:空输入 if not lists: return None # 边界处理2:过滤列表中的空链表(关键!避免递归时传入None) lists = [l for l in lists if l is not None] # 过滤后无有效链表 if not lists: return None # 启动分治合并 return self._merge(lists, 0, len(lists) - 1) def _merge(self, lists, left, right): # 分治终止条件:左右指针重合(只剩1个链表) if left == right: return lists[left] # 计算中点,拆分区间 mid = (left + right) // 2 # 递归合并左半区和右半区 left_list = self._merge(lists, left, mid) right_list = self._merge(lists, mid + 1, right) # 合并两个升序链表 return self._merge_two_lists(left_list, right_list) def _merge_two_lists(self, l1, l2): # 合并两个升序链表的核心逻辑 dummy = ListNode(0) # 虚拟头节点,简化拼接 curr = dummy # 双指针遍历两个链表,选择更小的节点拼接 while l1 and l2: if l1.val < l2.val: curr.next = l1 l1 = l1.next else: curr.next = l2 l2 = l2.next curr = curr.next # 拼接剩余未遍历完的链表(本身已是升序) curr.next = l1 if l1 else l2 # 返回合并后的真实头节点(跳过虚拟头) return dummy.next # ===================== 工具函数:用于测试 ===================== def build_linked_list(nums): """根据列表构建链表(如 [1,4,5] → 1→4→5)""" dummy = ListNode(0) curr = dummy for num in nums: curr.next = ListNode(num) curr = curr.next return dummy.next def print_linked_list(head): """打印链表(如 1→4→5 → [1,4,5])""" res = [] while head: res.append(head.val) head = head.next return res # ===================== 测试用例 ===================== if __name__ == "__main__": solution = Solution() # 测试用例1:常规场景(题目示例) lists1 = [ build_linked_list([1, 4, 5]), build_linked_list([1, 3, 4]), build_linked_list([2, 6]) ] merged1 = solution.mergeKLists(lists1) print("测试用例1结果:", print_linked_list(merged1)) # 预期:[1,1,2,3,4,4,5,6] # 测试用例2:包含空链表 lists2 = [ None, build_linked_list([5]), None, build_linked_list([1, 2, 3]), build_linked_list([4]) ] merged2 = solution.mergeKLists(lists2) print("测试用例2结果:", print_linked_list(merged2)) # 预期:[1,2,3,4,5] # 测试用例3:所有链表为空 lists3 = [None, None, None] merged3 = solution.mergeKLists(lists3) print("测试用例3结果:", print_linked_list(merged3)) # 预期:[] # 测试用例4:只有1个链表 lists4 = [build_linked_list([10, 20, 30])] merged4 = solution.mergeKLists(lists4) print("测试用例4结果:", print_linked_list(merged4)) # 预期:[10,20,30]# 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 return self._merge(lists, 0, len(lists) - 1) def _merge(self, lists, left, right): # 分治终止条件:左右指针重合 if left == right: return lists[left] mid = (left + right) // 2 # 递归合并左右两个子数组的链表 left_list = self._merge(lists, left, mid) right_list = self._merge(lists, mid + 1, right) # 合并两个升序链表 return self._merge_two_lists(left_list, right_list) def _merge_two_lists(self, l1, l2): # 合并两个升序链表的辅助函数 dummy = ListNode(0) curr = dummy while l1 and l2: if l1.val < l2.val: curr.next = l1 l1 = l1.next else: curr.next = l2 l2 = l2.next curr = curr.next # 拼接剩余节点 curr.next = l1 if l1 else l2 return dummy.next本文介绍了一种高效合并多个升序链表的分治算法。算法通过递归将链表数组不断拆分为更小的子问题(两两合并),最终将所有链表合并为一个有序链表。关键步骤包括:边界条件处理、递归分治拆分链表区间、合并两个有序链表的子问题。该算法时间复杂度为O(Nlogk),空间复杂度为O(logk),其中k为链表数量,N为总节点数。Python实现中使用了虚拟头节点简化合并操作,并通过过滤空链表优化性能。测试用例验证了算法在常规、空链表及单链表等情况下的正确性。