简单LeetCode 21动画补充中引导学习
合并两个有序链表
虚拟头节点 + 双指针归并
用虚拟头节点(dummy)挂住结果链表,双指针分别指向两条链的当前节点:谁小就接谁、然后谁后移;一条走完后把另一条剩下的整段直接接上。
时间复杂度 O(n + m)空间复杂度 O(1)
题单:面试热题
题目描述
给定两条升序排列的链表,把它们合并为一条新的升序链表并返回(新链表由原有节点拼接而成,不新建节点)。
学习目标
能说清虚拟头节点解决了什么特判,并能写出双指针合并 + 接剩余链的完整流程。
已完成 0 / 6 阶段
诊断
先问:为什么要造一个假节点
不用 dummy,直接维护结果链表的头和尾,会遇到哪些特判?dummy 改变了什么?
建议先完成当前阶段(提示 / 检查 / 自评),再进入下一步;也可以直接跳过。
解题思路
核心思想
用虚拟头节点(dummy)挂住结果链表,双指针分别指向两条链的当前节点:谁小就接谁、然后谁后移;一条走完后把另一条剩下的整段直接接上。
为什么需要它
链表不能随机访问,"合并两个有序序列"天然适合边走边接——这就是归并排序里 merge 那一步的链表版。
第一反应:直觉方案
每次在两条链的当前节点里找更小的那个插到结果里——方向对,但"结果链表的尾巴在哪"要额外维护,空链表的特判也多。
关键洞察
关键洞察是虚拟头节点:先造一个假节点当"结果链表的头",这样"接第一个节点"和其他所有节点完全一样,都是"接在尾巴后面",消灭了所有对空链表的特判;结束时返回 dummy.next。这个技巧在所有"构造一条新链表"的题目里通用。
时间复杂度 O(n + m)空间复杂度 O(1)
易错点
- 用 dummy 节点消除首节点特判,返回的是 dummy.next
- 循环条件是"两条链都还有节点";循环结束后把剩余的那一整段直接接上,不要逐个再比
- JS 里判空用 if (list1),Python 里用 if list1——空节点本身是假值
参考代码
参考代码
1function mergeTwoLists(list1, list2) {
2 const dummy = new ListNode(0); // 虚拟头节点
3 let tail = dummy;
4 while (list1 && list2) {
5 if (list1.val <= list2.val) {
6 tail.next = list1;
7 list1 = list1.next;
8 } else {
9 tail.next = list2;
10 list2 = list2.next;
11 }
12 tail = tail.next;
13 }
14 tail.next = list1 || list2; // 接上没走完的那条
15 return dummy.next;
16}
逐步演示
这道题目前是索引版:题面、解题思路与双语言代码已是完整内容; 逐步动画会按计划补充。