一、题目描述

JZ36两个链表的第一个公共结点
题目大意:给定两个链表A和B,他们尾部的几个结点可能是相同的,我们需要返回第一个公共结点的指针
注意审题:两个链表也可以没有公共结点,此时返回空指针即可

二、算法1(双指针)

算法思路

1.总体思路:我们可以分别用两个指针指向链表的头结点,然后一步一步地向后移动,当两个指针指向相同的结点时,直接返回即可
2.但是注意一个问题,由于两链表的长度不一定是相同的,因此我们需要预处理一下,保证两指针的相对位置重合
3.实现方法:先计算一下两条链表的长度len1, len2;若len1 > len2,则p1指针向后移动len1 - len2步;若len1 < len2,则p2指针向后移动len2 - len1步;len1 = len2时不变;这样预处理就完成了,最后两指针再同步向后移动即可
图片说明

代码实现(C++11)

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        int len1 = get_ListLength(pHead1);
        int len2 = get_ListLength(pHead2);
        ListNode *p1 = pHead1, *p2 = pHead2;
        if(len1 > len2){
            while(len1 > len2){
                p1 = p1->next;
                --len1;
                }
            }
         if(len2 > len1){
             while(len2 > len1){
                 p2 = p2->next;
                 --len2;
                 }
             }
         while(p1){
             if(p1 == p2) return p1;
             p1 = p1->next;
             p2 = p2->next;
             }
        return p1;
    }

    int get_ListLength(ListNode* head){
        int len = 0;
        while(head){
            head = head->next;
            ++len;
            }
        return len;
    }
};

时间复杂度:O(n + m), n和m分别是链表A,B的长度
空间复杂度:O(1)

三、算法2(哈希集合)

算法思路

1.总体思路:我们先将其中一条链表的所有结点存下来,再遍历另一条链表,若查找到了相同的结点,则直接返回;若遍历完了都没有找到,就返回空指针

代码实现(C++11)

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        unordered_set<ListNode*> s;
        ListNode *p1 = pHead1, *p2 = pHead2;
        while(p1){
            s.insert(p1);
            p1 = p1->next;
            }
        while(p2){
            if(s.count(p2)) return p2;
            p2 = p2->next;
            }
        return nullptr;
    }
};

时间复杂度:O(n + m), n和m分别是链表A,B的长度
空间复杂度:O(n)