160. 相交链表(Intersection of Two Linked Lists)

难度:简单 | 主题:链表、双指针

题目

给你两个单链表的头节点 headAheadB,找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

示例

 
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5]
 
输出:Reference of the node with value = 8
 

思路

先讲个故事:两条路汇成一条路

有两条路,一条从 A 村出发,一条从 B 村出发,但它们在某点汇合后共用一条通往 C 村的路。你想找到那个汇合点

你不知道每条路在汇合前各有多长。但你想到一个办法:让两辆车分别出发,走完自己的路后,绕到对方的起点再走一遍。当它们都走完”对方的路”时,刚好同时到达汇合点。


引导式推导:从哈希集到双指针

第 1 层:哈希集(直觉)

遍历 A,存所有节点到集合。遍历 B,第一个在集合中的节点就是交点。O(n) 空间。

第 2 层:双指针(最优)

 
pA 走 A → 再接 B
 
pB 走 B → 再接 A
 

设 A 长度为 a+c,B 长度为 b+c(c 是公共部分)。pA 走 a+c+b,pB 走 b+c+a,路程相等!

  • 如果有交点:pA 和 pB 在交点相遇

  • 如果无交点:最后同时到 None


graph LR

    subgraph 双指针路径

        A["pA: A头→交点→B头→交点<br/>路程: a+c+b"] --> M{"相遇?"}

        B["pB: B头→交点→A头→交点<br/>路程: b+c+a"] --> M

        M -->|是| Y["返回交点"]

        M -->|否| N["同时到 None"]

    end

    style Y fill:#ffd700

解法时间空间
哈希集O(a+b)O(a)
双指针O(a+b)O(1)

代码

 
def getIntersectionNode(self, headA, headB):
 
    if not headA or not headB:
 
        return None
 
    pA = headA
 
    pB = headB
 
    while pA != pB:
 
        pA = pA.next if pA else headB
 
        pB = pB.next if pB else headA
 
    return pA
 

复杂度

指标解释
时间O(a+b)a, b 为两链表长度
空间O(1)两个指针

实战考量

频率分析

出现在:字节/美团/微软 常考,约 30% 的 AI Agent 常会出这题。重点看你能不能讲清楚”为什么两指针走的路程相等”

延伸思考

Q:证明两指针一定会相遇?

A:设 A 长 a+c, B 长 b+c。pA 走 a+c+b,pB 走 b+c+a,路程相等,必在交点相遇。

Q:如果链表有环呢?

A:先分别用快慢指针判环。有环时本方法不适用。

Q:先算长度差再对齐怎么做?

A:算两链表长度,长链表先走差值步,然后同步走。代码更长但思路更直观。

Q:不相交时返回什么?

A:最后 pA = pB = None,循环退出,返回 None。

易错点

  • 条件用 pA != pB,不是 pA.next != pB.next

  • 三目运算 pA.next if pA else headB 而不是 pA.next if pA.next else headB

  • 不相交时能正确处理(同时变 None)


生活类比

相交链表 → 两条路汇合

两辆车分别从两条路出发,走完自己的路后抄对方的起点再走一次。路程相同,所以同时到达汇合点。如果永远到不了同一个点?那说明两条路根本没有汇合,它们都开到了虚空(None)。


相关题目

题目关系
141环形链表双指针链表遍历技巧同源
142环形链表II双指针找环入口同源

→ 返回题单:LeetCode学习路线图 > 四、链表

速记卡(面试闪卡)

Q1:一句话讲清「160. 相交链表(Intersection of Two Linked Lists)」到底是什么?

A:相交链表找两链表的公共起点,双指针走对方路必相遇。

Q2:一、题目要求 —— 怎么理解? —— 怎么理解?

A:像找两条路的汇合点:给两链表头,返回它们相交的起始节点,没交点返回 null;难点在汇合前长度未知。英语:intersection node(相交节点)。

Q3:二、双指针走对方路 —— 怎么理解? —— 怎么理解?

A:像两辆车抄对方起点:pA 走完 A 接 B、pB 走完 B 接 A,路程都是 a+c+b,必在交点或同时到 null 相遇。比哈希集省空间。英语:two-pointer / path swap。

Q4:三、代码要点 —— 怎么理解? —— 怎么理解?

A:像交替跑道:while pA!=pB 就 pA=pA.next?headB、pB=pB.next?headA,相遇即返回;用 pA!=pB 而非 pA.next。英语:pointer chasing。

Q5:四、复杂度与易错点 —— 怎么理解? —— 怎么理解?

A:像配平路程:时间 O(a+b) 空间 O(1);易错在三目写 pA.next 而非 pA、不相交时同时变 null 正常返回。英语:O(a+b) time / O(1) space。

Q6:核心速记主线有哪些?

  • 找两链表公共起点,无则返回 null

  • 双指针互换头:路程相等必相遇

  • 循环用 pA!=pB,三目接对方头

  • 时间O(a+b)空间O(1),优于哈希集

口诀

A:相交链表两路开,抄对方头必相逢;

路程相等同时到,交点 null 自然明。

指针不遇不罢休,三目接 head 莫慌;

时间 O(a+b) 空间一,双针解法最稳当。

相关链接