题目描述

✅ 160. 相交链表

image-20260928183827802

image-20260928183827804

image-20260928183827806

image-20260928183827807

题意分析

给定两条无环单链表,返回它们的第一个公共节点;如果没有公共节点,返回空。这里的相交指两条链引用了同一个节点对象,节点值相同并不代表相交。

单链表的节点只有一个后继,因此一旦两条链走到同一个节点,之后的整段后缀都会相同,不会再分开。要求找到共享后缀的入口,并保持两条链表的原有结构。

解法:双指针交替遍历

核心思路

[!blue]

如果两条链等长,从各自头节点同时前进,就会同时到达第一个公共节点。一般情况下,两条链在交点之前的长度不同,直接同步前进可能错过彼此,因此要先消除这段长度差。

不必实际计算长度:令 p 先走 A 再走 B,令 q 先走 B 再走 A。两者都走过对方的独立前缀后,额外路程就相互抵消了。

设 A、B 在相交前的独立前缀长度分别为 a、b,公共后缀长度为 c。交换链表后,到达公共入口之前,p 经过 a + c + b 个节点,q 经过 b + c + a 个节点;两者还各经历一次从空节点切换到另一链头的更新。总路程相同,所以会同步到达公共入口。若本来就已经对齐,则会在第一次遍历时提前相遇。

如果不相交,两者走完 A、B 两条链的总长度同样相等,最终会同时成为空指针。因此用 p != q 作为循环条件,既能在交点结束,也能在无交点时结束,不需要额外标记或修改链表。

解题步骤

  1. 初始化 p = headA、q = headB。
  2. 当两个指针不是同一个节点时,分别更新一次它们的位置。
  3. 若 p 非空,就前进到 p.next;若已经为空,就切换到 headB。
  4. 对 q 做对称处理:非空时前进,为空时切换到 headA。
  5. 两者相同时返回 p。它可能是共享后缀的入口,也可能是表示不相交的空指针。

代码实现

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p = headA;
        ListNode q = headB;

        // 相同节点或同时为空都会结束,比较的是对象身份。
        while (p != q) {
            // 走到空后转向另一条链,抵消两条前缀的长度差。
            p = p == null ? headB : p.next;
            q = q == null ? headA : q.next;
        }

        return p;
    }
}
func getIntersectionNode(headA *ListNode, headB *ListNode) *ListNode {
    p, q := headA, headB

    // 相同节点或同时为空都会结束,比较的是对象身份。
    for p != q {
        // 走到空后转向另一条链,抵消两条前缀的长度差。
        if p == nil {
            p = headB
        } else {
            p = p.Next
        }

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

    return p
}

复杂度分析

设两条链表的长度分别为 m、n。

  • 时间复杂度:$O(m+n)$,每个指针最多遍历两条链各一次,加上常数次切换就会结束。
  • 空间复杂度:$O(1)$,只使用两个指针,不记录节点集合。

关键点总结

[!green]

  • 相交意味着共享后缀,所以问题的关键是消除入口之前的长度差。
  • 两指针交换遍历顺序,使它们在相遇前走过相同长度的路程。
  • 两个空指针也相等,因此同一个终止条件覆盖有交点和无交点。

易错点总结

[!yellow]

  • 比较节点值会把两个独立但数值相同的节点误判为相交,必须比较节点引用。
  • 应先允许指针到达空节点,再在下一轮切换链头;若在尾节点直接切换,无交点时可能永远循环。
  • 循环条件若额外要求两个指针都非空,就会在第一次走完较短链时提前退出,来不及消除长度差。
  • 本题保证链表无环。不能把这套“走到空节点再切换”的方法直接用于带环链表。

相似题目

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