LeetCode-双指针合并 (归并法)
🧠 涉及两个有序链表的合并、排序问题
一句话结论:
👉 “谁小谁先走”。这就是拉链原理:同时遍历两条链表,比较当前头节点,较小的那个接在结果链表后面,然后向前走一步。
⭐ 核心逻辑
哨兵节点 (Dummy Node):只要一个 dummy,用来挂接结果。
拉拉链 (Comparison):while 循环同时检查两个链表,谁小就把谁接上,被接走的那个指针后移,没被接走的保持不动。
接余部 (Post-processing):这是链表对比数组的巨大优势 —— 当一条链表遍历完,另一条链表剩下的部分不需要遍历,直接把指针指过去就行(因为剩下的肯定也是有序的)。
⭐ 模板
初始化
//虚拟头节点(锚点)
ListNode dummy = new ListNode(0);
ListNode tail = dummy;//两个并行指针
ListNode p1 = l1;
ListNode p2 = l2;循环处理(控制指针移动)
//同时遍历,按规则选择
while (p1 != null && p2 != null) {if (choose(p1, p2)) {
tail.next = p1;
p1 = p1.next;
} else {
tail.next = p2;
p2 = p2.next;
}tail = tail.next;
}//接上剩余部分
tail.next = (p1 != null) ? p1 : p2;返回结果
return dummy.next;
Notice:
1.最大的优势:接余部(不要写循环!)
这是链表对比数组最大的优势,也是这个模板最容易写“多余”的地方。
直接一个 if 把剩下的整条链表挂在后面。因为剩下的部分本身就是有序的,不需要再遍历。
✅ 正确(利用链表特性,O(1) 操作)
if (l1 != null) tail.next = l1;
if (l2 != null) tail.next = l2;
❌ 错误/低效(把链表当数组用了,O(N) 操作)
while (l1 != null) {
tail.next = l1;
l1 = l1.next;
tail = tail.next;
}
相关练习题
1. LeetCode 21. 合并两个有序链表
题意: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
2. LeetCode 23. 合并 K 个升序链表
题意: 给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
3. LeetCode 148. 排序链表
题意: 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

