LeetCode面试HOT100——160. 相交链表

相交链表双指针最优解

相交链表代码超详细解析(双指针最优解)

这段代码是力扣「相交链表」问题的 双指针最优解(时间复杂度O(n+m)、空间复杂度O(1)),核心思路是「让两个指针走相同的总路程,最终在相交节点相遇」。下面从「问题本质→代码逻辑→分步演示→关键细节」帮你彻底吃透。

一、先明确问题本质

1. 相交链表的定义

两个链表相交,指的是 节点引用相同(不是值相同),即从相交节点开始,后续所有节点都完全共用(结构上是"Y"形,不是"X"形)。

例:链表A:1→2→3→4→5,链表B:6→7→3→4→5,相交节点是3(两个链表的3是同一个节点,后续45也共用)。

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)(仅用两个指针),是最优解法。

五、总结

这段代码的核心是「等效路程法」:

  1. 双指针分别从两个链表头出发,遍历完一个链表后立刻转向另一个链表;

  2. 总路程相同 → 必然同时到达终点(或相交点);

  3. 循环终止时,h1和h2要么是相交节点,要么都是null,直接返回即可。

记住一句话:"你走我的路,我走你的路,我们终将相遇(或一起到尽头)",就能轻松理解并默写这段代码!如果还是不理解,建议动手画一画指针移动的每一步,可视化后会瞬间清晰。

相关推荐
裤裤兔1 小时前
利用matlab进行FDR校正的实现方式
数据结构·算法·matlab·多重比较矫正·校正·fdr
野蛮人6号1 小时前
力扣热题100道之31下一个排列
算法·leetcode·职场和发展
子一!!1 小时前
哈希桶,元素插入逻辑实现
算法·哈希算法
吃着火锅x唱着歌1 小时前
LeetCode 454.四数相加II
算法·leetcode·职场和发展
敲代码的嘎仔1 小时前
LeetCode面试HOT100—— 206. 反转链表
java·数据结构·学习·算法·leetcode·链表·面试
雨中飘荡的记忆1 小时前
设计模式之适配器模式详解
java·设计模式·适配器模式
丝斯20111 小时前
AI学习笔记整理(19)—— AI核心技术(深度学习3)
人工智能·笔记·学习
自然语1 小时前
深度学习时代结束了,2025年开始只剩下轮廓
数据结构·人工智能·深度学习·学习·算法
海天一色y1 小时前
Leetcode07-整数反转
算法