资讯动态

力扣Hot100:合并两个有序链表的算法解析与实践

发布时间:2026/9/12 22:29:00 来源:尧图企业网站定制
1. 力扣Hot100第27题合并两个有序列表解析链表操作是算法面试中的高频考点而合并两个有序链表更是基础中的基础。这道题出现在力扣Hot100中说明它在实际面试中的出现概率极高。作为刷过300链表题的老手我发现很多初学者容易在这里翻车——不是逻辑理不清就是边界条件处理不好。今天我们就来彻底拆解这个问题从暴力解法到最优解从代码实现到复杂度分析一次性讲透。2. 问题描述与示例分析2.1 题目要求给定两个升序排列的链表list1和list2将它们合并为一个新的升序链表并返回。新链表应该通过拼接给定的两个链表的节点组成。示例 输入list1 [1,2,4], list2 [1,3,4] 输出[1,1,2,3,4,4]2.2 数据结构理解链表节点通常定义为class ListNode: def __init__(self, val0, nextNone): self.val val self.next next与数组不同链表通过指针连接合并时只需修改节点的next指针不需要额外空间存储新链表。这是链表合并相比数组合并的优势所在。3. 解法一迭代法推荐3.1 算法思路创建哑节点(dummy)作为新链表的起始点维护一个current指针指向当前节点比较list1和list2当前节点的值将较小者接在current后面移动较小者所在链表的指针到下一个节点重复直到某条链表遍历完毕将剩余链表直接接在合并链表后面3.2 代码实现def mergeTwoLists(list1: ListNode, list2: ListNode) - ListNode: dummy ListNode() current dummy while list1 and list2: if list1.val list2.val: current.next list1 list1 list1.next else: current.next list2 list2 list2.next current current.next current.next list1 if list1 else list2 return dummy.next3.3 复杂度分析时间复杂度O(nm)n和m分别是两个链表的长度空间复杂度O(1)只使用了常数级别的额外空间注意使用哑节点可以避免处理头节点的特殊情况这是链表题中的常用技巧4. 解法二递归法思维训练4.1 算法思路递归的核心思想是比较两个链表头节点的值将较小者作为当前节点对剩下的链表继续递归合并返回当前节点4.2 代码实现def mergeTwoLists(list1: ListNode, list2: ListNode) - ListNode: if not list1: return list2 if not list2: return list1 if list1.val list2.val: list1.next mergeTwoLists(list1.next, list2) return list1 else: list2.next mergeTwoLists(list1, list2.next) return list24.3 复杂度分析时间复杂度O(nm)空间复杂度O(nm)递归调用栈的空间5. 边界条件与异常处理5.1 常见边界情况其中一个链表为空两个链表都为空链表中有重复元素链表长度差异很大5.2 测试用例设计# 用例1常规情况 list1 1-3-5 list2 2-4-6 预期1-2-3-4-5-6 # 用例2一个链表为空 list1 None list2 1-2 预期1-2 # 用例3有重复元素 list1 1-1-1 list2 2-2-2 预期1-1-1-2-2-26. 算法优化与变种6.1 优化空间使用迭代法已经是空间最优解递归法可以改用尾递归优化但Python不支持尾递归优化6.2 相关变种题目合并K个有序链表力扣23题合并两个有序数组力扣88题链表排序力扣148题7. 实际工程中的应用场景数据库多路归并排序分布式系统中的日志合并版本控制系统中的分支合并大数据处理中的MapReduce合并阶段8. 常见错误与Debug技巧8.1 典型错误忘记处理链表剩余部分修改指针顺序错误导致链表断裂没有使用哑节点导致头节点处理复杂8.2 Debug方法画图辅助理解指针变化使用小规模测试用例手动模拟打印中间状态检查指针指向# Debug打印函数 def print_list(head): while head: print(head.val, end-) head head.next print(None)9. 不同语言实现对比9.1 C实现ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode dummy(0); ListNode* current dummy; while (list1 list2) { if (list1-val list2-val) { current-next list1; list1 list1-next; } else { current-next list2; list2 list2-next; } current current-next; } current-next list1 ? list1 : list2; return dummy.next; }9.2 Java实现public ListNode mergeTwoLists(ListNode list1, ListNode list2) { ListNode dummy new ListNode(0); ListNode current dummy; while (list1 ! null list2 ! null) { if (list1.val list2.val) { current.next list1; list1 list1.next; } else { current.next list2; list2 list2.next; } current current.next; } current.next list1 ! null ? list1 : list2; return dummy.next; }10. 进阶思考与扩展如果链表是降序排列如何修改如何在不修改原链表的情况下合并创建全新节点如何实现稳定合并保持相同元素的原始相对顺序如果链表有环怎么处理对于降序链表可以反转链表后合并或者直接修改比较逻辑。创建新节点会增加空间复杂度但有时是业务需求。稳定合并需要额外注意相等时的处理顺序。有环链表需要先检测环这是另一个经典问题。在实际面试中面试官可能会追问这些变种问题来考察候选人的思维灵活性。我的建议是先把基础解法练到肌肉记忆再逐步挑战这些变种问题。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价