相交链表双指针最优解
相交链表代码超详细解析(双指针最优解)
这段代码是力扣「相交链表」问题的 双指针最优解(时间复杂度O(n+m)、空间复杂度O(1)),核心思路是「让两个指针走相同的总路程,最终在相交节点相遇」。下面从「问题本质→代码逻辑→分步演示→关键细节」帮你彻底吃透。
一、先明确问题本质
1. 相交链表的定义
两个链表相交,指的是 节点引用相同(不是值相同),即从相交节点开始,后续所有节点都完全共用(结构上是"Y"形,不是"X"形)。
例:链表A:1→2→3→4→5,链表B:6→7→3→4→5,相交节点是3(两个链表的3是同一个节点,后续4、5也共用)。
2. 核心痛点
两个链表长度可能不同(设为n和m),直接遍历无法同步到达相交节点。
常规思路(如哈希表存节点)需要额外空间,而双指针法能做到「无额外空间」求解。
3. 算法核心思想(等效路程法)
让两个指针分别从链表A、B的头节点出发,按以下规则移动:
-
指针h1遍历完链表A(走到null)后,立刻转向链表B的头节点继续遍历;
-
指针h2遍历完链表B(走到null)后,立刻转向链表A的头节点继续遍历;
-
最终,两个指针会走 相同的总路程(n+m):
-
若两链表相交:两指针会在相交节点相遇(h1 == h2);
-
若不相交:两指针会同时走到null(h1 == h2 == null)。
-
原理:总路程相同 + 速度相同(每次走1步),必然同时到达终点(或相交点)。
二、代码逐行拆解(带注释)
Java
三、分步演示(两种场景)
为了直观理解,分「两链表相交」和「两链表不相交」两种情况演示。
场景1:两链表相交(A长度=5,B长度=4,相交节点为3)
链表A:1→2→3→4→5(节点:A1、A2、A3、A4、A5)
链表B:6→7→3→4→5(节点:B1、B2、A3、A4、A5)
总路程:5+4=9步,两指针各走9步后相遇。
| 步数 | h1(从A出发) | h2(从B出发) | 备注 |
|---|---|---|---|
| 0 | A1(1) | B1(6) | 初始状态 |
| 1 | A2(2) | B2(7) | 均未到终点,继续走 |
| 2 | A3(3) | A3(3) | 此时h1=h2,相遇!循环结束 |
| 关键:h1走了2步到A3,h2走了2步到A3(总路程都是2,因两链表在A3相交,后续路程相同,提前相遇)。 |
场景2:两链表不相交(A长度=3,B长度=2)
链表A:1→2→3→null
链表B:4→5→null
总路程:3+2=5步,两指针各走5步后同时到null。
| 步数 | h1(从A出发) | h2(从B出发) | 备注 |
|---|---|---|---|
| 0 | A1(1) | B1(4) | 初始状态 |
| 1 | A2(2) | B2(5) | 均未到终点 |
| 2 | A3(3) | null(B遍历完) | h2转向A的头(A1) |
| 3 | null(A遍历完) | A1(1) | h1转向B的头(B1) |
| 4 | B1(4) | A2(2) | 继续走 |
| 5 | B2(5) | A3(3) | 继续走 |
| 6 | null(B遍历完) | null(A遍历完) | h1=h2=null,循环结束 |
| 关键:两指针都走了6步(总路程3+2=5?实际因null也算一步,最终同时到null,返回null正确)。 |
四、关键细节与避坑点
1. 为什么循环条件是h1 != h2?
-
若相交:h1和h2会在相交节点相等,循环终止,返回该节点;
-
若不相交:h1和h2会同时走到null(h1h2null),循环终止,返回null(符合题目要求)。
2. 为什么指针走到null后要转向另一个链表的头?
核心是「凑齐相同总路程」。假设A长度n,B长度m:
-
h1的路径:A的n个节点 + B的m个节点(总n+m);
-
h2的路径:B的m个节点 + A的n个节点(总m+n);
总路程相同,速度相同(每次1步),必然同时到达终点(或相交点)。
3. 会不会陷入死循环?
不会!因为两指针的总路程是固定的(n+m),最多走n+m步后,必然会同时走到null(h1==h2),循环一定会终止。
4. 边界情况是否覆盖?
-
其中一个链表为空(headAnull):h1初始为null,h2遍历完B后转向A(null),最终h1h2==null,返回null(正确);
-
两个链表长度相同且相交:两指针同步走,直接在相交节点相遇;
-
两个链表长度相同且不相交:同时走到null,返回null。
5. 为什么比哈希表方法更优?
哈希表方法(存A的所有节点,再遍历B查找)的时间复杂度是O(n+m),但空间复杂度是O(n)(需要存A的节点);而双指针法空间复杂度是O(1)(仅用两个指针),是最优解法。
五、总结
这段代码的核心是「等效路程法」:
-
双指针分别从两个链表头出发,遍历完一个链表后立刻转向另一个链表;
-
总路程相同 → 必然同时到达终点(或相交点);
-
循环终止时,h1和h2要么是相交节点,要么都是null,直接返回即可。
记住一句话:"你走我的路,我走你的路,我们终将相遇(或一起到尽头)",就能轻松理解并默写这段代码!如果还是不理解,建议动手画一画指针移动的每一步,可视化后会瞬间清晰。