AcWing 66. 两个链表的第一个公共结点

29

题目

输入两个链表,找出它们的第一个公共结点。
当不存在公共节点时,返回空节点。

数据范围
链表长度[1,2000]

样例

给出两个链表如下所示:
A:        a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

输出第一个公共节点c1

备注

第一个公共结点的含义
第一个公共结点,即这个结点后的所有结点相等。
也就是出现第一个公共结点后,从此结点开始到链表结尾,两链表的结点数量一致,结点内容也一致

本题调试框内输入输出的含义
如果大家打算在调试框内构造输入输出,格式如下:
输入包括三行,例如:

[a, b, c, d, e]
[f, g, h]
3

表示的两个链表分别是:

  • 第一个链表即输入第一行的链表:[a, b, c, d, e]
  • 第二个链表即将输入第二行的链表接到第一行链表的第3个节点后面(链表节点下标从1开始):[a, b, c, f, g, h]
  • 如果输入第三行为-1,表示两个链表不相交,此时第二个链表即输入第二行的链表:[f, g, h]

输出包括一行:

  • 如果两个链表相交,则输出相交节点的权值,即c
  • 如果不相交,则输出null

巧妙的思路

一共有两种情况,第一种情况是两个链表存在公共结点,第二种情况是两个链表不存在公共结点。
如图所示,我们定义两个指针p、q,同时定义每一个指针的路线,其中:

  • p指针从第一个链表的起点出发,到达第一个链表尾部(即空结点)后,转到第二个链表起点继续前进,直到和q指针相遇为止(也就是p和q相等)
  • q指针从第二个链表的起点出发,到达第二个链表尾部(即空结点)后,转到第一个链表起点继续前进,直到和p指针相遇为止(也就是p和q相等)

我们将距离分别设置为如图所示的a、b、c,那么:

  • 当两个链表存在公共结点时,两个指针p、q走过的路径长度分别为:a+c+bb+c+a,走过的总长度相同。
  • 当两个链表不存在公共结点时,两个指针p、q走过的路径长度分别为:a+bb+a
    image-1659411560452

题解

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) {
        auto p = headA, q = headB;
        while (p != q) {
            p = p ? p->next : headB;
            q = q ? q->next : headA;
        }
        return p;
    }
};

题目链接

https://www.acwing.com/problem/content/62/