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,直接返回即可。

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

相关推荐
唐青枫8 分钟前
Java SLF4J 实战指南:从日志门面到 Logback、MDC 和链路追踪
java
众人皆醒我独醉31 分钟前
etcd,其实不是你以为的"数据库"——Kubernetes 大脑的六个反直觉真相
面试·kubernetes
jvmind_dev40 分钟前
Java GC 实战指南(番外篇):被忽视的隐形杀手 —— Class Unloading 如何拖垮 GC
java·后端
可编程芯片开发42 分钟前
基于MPPT最大功率跟踪的离网光伏发电系统Simulink建模与仿真
算法
An_s44 分钟前
机器学习python之识别图中物品信息
java·linux·开发语言
AI科技星1 小时前
线性算子不是空间映射函数,是全域双螺旋场之间拉伸、旋转、耦合、坍缩的跨空间标准化变换载体《全域数学vs传统数学:人类文明进阶200讲》第80讲
线性代数·算法·矩阵·数据挖掘·回归·乖乖数学·全域数学
米罗篮1 小时前
矩阵快速幂 (Exponentiation By Squaring Applied To Matrices)
c++·线性代数·算法·矩阵
Hyyy1 小时前
Electron-Vite是什么,和Vite有什么区别
前端·面试
dream_home84071 小时前
图像算法模型NPU适配与算法服务实战指南
人工智能·python·算法·npu 图像服务
AIGS0011 小时前
跨越语义鸿沟:企业本体语义平台的构建与落地
java·人工智能·python·机器学习·人工智能ai大模型应用