题目描述
思路解析动画文字版
链表本来已经分别有序,没必要全部打散排序。
比较 list1 和 list2 的当前节点,把更小的接到 tail 后面,然后 tail 前进。
dummy 起步 · 三行同屏:三行同时看:上面两个是待比较链表,下面是结果链表。tail 从 dummy 出发,专门负责接新节点。
比较决策 · 1 和 1:关键的比较决策帧:每一步只看两个链表的头。这里 1 和 1 相等,为保持稳定,约定相等时选 list1。
接上 list1 的 1:把胜出的节点接到 tail 后面,然后 tail 前进。tail 不前进,下一次就会覆盖刚接上的节点。
比较决策 · 2 和 1:现在比较 2 和 1,list2 的 1 更小,于是接 list2 的 1。每一步都能看清「谁更小、谁被接走」,而不是直接跳到最终结果。
接上 list2 的 1:接完 list2 的 1,tail 再次来到结果链表尾部。接下来只重复“比较→接上→前进”。
一边空了 · 剩余整体接上:当一个链表空了,另一边剩下的部分本来就是有序的,可以整段接上,不需要逐个新建节点。
关键帧慢放 · 接更小的头那一刻:慢放接节点这一刻。比较两个头:2 比 3 小,就把 list1 的 2 接到 tail 后面,tail 前进到 2,同时 list1 的指针也前进。每一步只接更小的那个头,这就是合并的全部秘密。而 dummy 的作用,是让接第一个节点和接后面的节点用同一行代码。
链表题里 dummy 能消灭很多头结点特判。
边界三连:空链表和重复值,都被 dummy + tail 自然覆盖。
雷区实演 · 忘记 tail 前进:如果接上节点后 tail 不前进,下一次 tail.next 会覆盖刚接的节点。
三个高频追问。第一,能递归:较小的头接「递归合并剩余」的结果,但调用栈 O(m+n)。第二,不新建节点,复用原节点只改 next,空间 O(1)。第三,dummy 哨兵的意义,是让接第一个节点和接后续节点用同一套逻辑,免去头节点特判。
这题学完不要乱跳,下一步去 对应专题 连刷同类题;卡住时用 AI 答疑追问“为什么这一步成立”,比只背答案更稳。
参考代码
class Solution: def mergeTwoLists(self, list1, list2): dummy = ListNode(0) tail = dummy while list1 and list2: if list1.val <= list2.val: tail.next = list1 list1 = list1.next else: tail.next = list2 list2 = list2.next tail = tail.next tail.next = list1 or list2 return dummy.next复杂度
- 时间复杂度:O(m+n),每个节点只接一次
- 空间复杂度:O(1),迭代写法只用几个指针
可套用的代码模板
这一步不再重复本题答案,而是抽成可迁移的填空骨架:先说清状态/容器含义,再把“何时查、何时记、何时结算”填进去。
# 链表题先固定三件事:dummy、当前指针、下一跳dummy = ListNode(0)tail = dummywhile 还有节点要处理: nxt = 当前节点.next # 改指针前先存后继 tail.next = 选中的节点 # 只改一根箭头 tail = tail.next # tail 必须跟着走 当前指针 = nxtreturn dummy.next易错点
面试追问把动画讲成自己的话
追问递归能做吗?
追问会新建节点吗?
追问为什么要用 dummy 哨兵?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
重排链表
LeetCode 143 · 中等 · 沿着 链表 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题