题目重点:两个指针走完各自链表后切换到另一条,长度差自动抵消;澄清共享节点和环的边界。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版链表无环,交集按节点对象身份判断,一旦共享某节点,之后尾部全部共享;没有交点返回 None。
- 不同节点即便 value 相同也不算相交;若允许环,需单独检测环并分类讨论,不把常规双指针直接套用。
解题路线
- 指针 p 从 A、q 从 B 出发,每步前进;到 None 时分别切到 B、A 头。两人最多各走长度 len(A)+len(B),若共享尾部就会在首个共享节点同相位相遇。
- 设 A 独有 a 个节点、B 独有 b 个、公共尾 c 个;p 总路径 a+c+b,q 为 b+c+a,故切换后同时进入公共段。若不相交,两者最终都到 None。
- 比较 `is`/指针地址而非值;额外空间仅两个游标。可用长度对齐法先算两表长度、长表先走差值,仍 O(1) 空间。
手动走一遍
A: 1→2→X→Y,B: 3→X→Y,两指针切换后在同一个 X 节点相遇;若两个不同节点的 value 都是 X,不相交。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
class Node:
def __init__(self, value, next=None):
self.value = value
self.next = next
def first_intersection(a: Node | None, b: Node | None) -> Node | None:
"""Acyclic lists; intersection is node identity, not equal values."""
p, q = a, b
while p is not q:
p = b if p is None else p.next
q = a if q is None else q.next
return p
复杂度
时间 O(A+B),额外空间 O(1)。训练代码 15,000 组随机共享/不共享尾链与独立节点集合 oracle 对照。
易错点与追问
容易失分的边界
- 按节点 value 而非身份判断交点。
- 无交点时不切换到 None,造成死循环。
- 忘记一表为空。
- 将允许环作为默认情况,却未先检测环。
- 只返回任意相同值,不保证首个共享节点。
继续深挖
- 有环且环入口不同怎样判断交点?
- 如何用长度对齐法证明同样正确?
- 两条链表可被并发修改时算法前提如何变化?
