题目描述

✅ 面试题 02.07. 链表相交

image-20260928224107860

image-20260928224107861

image-20260928224107862

image-20260928224107863

题意分析

给定两条无环单链表,返回它们第一个共享的节点;不相交时返回空。相交表示两个引用指向同一个节点对象,而不是两个不同节点恰好具有相同的值。

单链表每个节点只有一个后继,因此一旦相交,后面的整段链表都会共享。两条链各自的独有前缀长度可能不同,直接从两个头同步前进,未必能同时到达交点;需要先消除这段长度差。

解法:双指针交换链表头

核心思路

[!blue]

两个指针分别从 headA、headB 出发,每轮同步前进一步。某个指针走到空后,下一步转到另一条链表的头,形成先走 A 再走 B、先走 B 再走 A 的两条路线。整个过程只移动局部指针,不改动任何链表连接。

设两条链独有前缀长度分别为 a、b,共享后缀长度为 c。若第一轮没有提前相遇,换头后,A 指针走到共享入口所经过的节点路程是 a + c + b,B 指针则是 b + c + a;两边还各有一次从空切换到另一链头的操作,总步数仍相同。因此它们会同时到达第一个共享节点。

两个独有前缀等长时,可能第一轮就相遇,不需要真的换头;两个头本来就相同也会直接返回。比较的是节点身份,所以不会在独有前缀中因为值相同而误判。

如果没有共享节点,两条路线都走完两条链表后,会同时到达空,循环同样结束并返回空。必须允许指针先走到空,再按同一规则换头;不能因为一侧先为空就提前判定不相交。

解题步骤

  1. 令两个指针分别指向 headA、headB。
  2. 只要两个指针不是同一个节点,就各更新一步。
  3. 非空指针移动到后继,空指针切换到另一条链表的头。
  4. 两指针相等时返回任意一个;结果可能是共享节点,也可能是空。

代码实现

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;

        // 两个指针各走两条链表,总路程一致后自然消除长度差。
        while (curA != curB) {
            if (curA == null) {
                // 走完一条后转到另一条,抵消两个独有前缀的长度差。
                curA = headB;
            } else {
                curA = curA.next;
            }

            if (curB == null) {
                curB = headA;
            } else {
                curB = curB.next;
            }
        }

        return curA;
    }
}
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    curA := headA
    curB := headB

    // 两个指针各走两条链表,总路程一致后自然消除长度差。
    for curA != curB {
        if curA == nil {
            // 走完一条后转到另一条,抵消两个独有前缀的长度差。
            curA = headB
        } else {
            curA = curA.Next
        }

        if curB == nil {
            curB = headA
        } else {
            curB = curB.Next
        }
    }

    return curA
}

复杂度分析

  • 时间复杂度:$O(m+n+1)$,包含走到空后切换另一链头的操作。
  • 空间复杂度:$O(1)$,不改变链表。

关键点总结

[!green]

  • 相交后共享整个后缀,不是两条链中恰好出现相同数值。
  • 允许先到空再切换,两边必须采用一致规则。

易错点总结

[!yellow]

  • 按 val 判断相等会把不同节点误判成交点。
  • 每次从头重新搜索另一个链表会增加不必要的重复遍历。
  • 只同步从两头走一次,长度不同就可能错过交点。

相似题目

题目 难度 关联与区别
补充题 119. 链表相交判定(允许有环) 中等 本题两链表无环,切换链头可消除长度差;允许带环后还需区分入环点与同环情形。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2025/91248679
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!