/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
  public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if (pHead1 == nullptr || pHead2 == nullptr) {
            return nullptr;
        }
        ListNode* p1 = pHead1;
        ListNode* p2 = pHead2;
        while (p1 != p2) {
            p1 = (p1 == nullptr) ? pHead2 : p1->next;
            p2 = (p2 == nullptr) ? pHead1 : p2->next;
        }
        return p1;
    }
};

为了解决这个问题,我们需要找到两个无环单链表的第一个公共节点。如果存在公共节点,则返回该节点;否则返回空。我们将使用双指针技巧来高效地解决这个问题,确保时间复杂度和空间复杂度满足要求。

方法思路
问题分析:两个无环单链表如果有公共节点,那么从第一个公共节点开始,后续的所有节点都是共享的。我们的任务是找到这个第一个公共节点。

关键观察:使用两个指针分别遍历两个链表。当一个指针到达链表末尾时,将其重定向到另一个链表的头部。这样,两个指针会在第一个公共节点相遇,因为它们遍历的总长度相同(两个链表的长度和)。

算法选择:使用双指针法,无需计算链表长度,通过遍历两次链表(每个指针各遍历两个链表一次)来找到公共节点。

代码解释:
初始化指针:使用两个指针 p1 和 p2 分别指向两个链表的头节点 pHead1 和 pHead2。

遍历链表:当 p1 和 p2 不相等时,继续遍历。如果 p1 到达链表末尾,则将其重定向到 pHead2;同样,如果 p2 到达链表末尾,则将其重定向到 pHead1。

相遇点:当 p1 和 p2 相遇时,该节点即为第一个公共节点。如果没有公共节点,两者会同时到达 nullptr,循环结束并返回 nullptr。

这种方法确保了在 O(n) 时间复杂度和 O(1) 空间复杂度内解决问题,高效且简洁。