剑指offer36_两个链表的第一个公共结点_题解

两个链表的第一个公共结点

题目描述

输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

分析

方案一:双指针法

思路:我们使用两个指针 p1,p2 分别指向两个链表 pHead1,pHead2 的头结点,然后同时分别逐结点遍历,当 p1 到达链表 pHead1 的末尾时,重新定位到链表 pHead2 的头结点;当 p2 到达链表 pHead2 的末尾时,重新定位到链表 pHead1 的头结点。这样,当它们相遇时,所指向的结点就是第一个公共结点。

理解:两个链表长度分别为L1+C、L2+C, C为公共部分的长度(包含末尾的NULL),按照楼主的做法: 第一个人走了L1+C步后,回到第二个人起点走L2步;第2个人走了L2+C步后,回到第一个人起点走L1步。 当两个人走的步数都为L1+L2+C时就两个指针就相遇了。如果没有公共结点就会在链表尾部NULL的位置相遇。

代码

/**
1.时间复杂度:O(M+N)
M+N代表两个链表的长度之和
2.空间复杂度:O(1)
只有指针p1和指针p2占用了额外空间
**/
class Solution
{
public:
    ListNode *FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
    {
        ListNode *p1 = pHead1, *p2 = pHead2;
        while (p1 != p2)
        {
            p1 = p1 ? p1->next : pHead2;
            p2 = p2 ? p2->next : pHead1;
        }
        return p1;
    }
}; 

方案二:链表等长法

先统计两个链表的长度,如果两个链表的长度不一样,就让链表长的先走,直到两个链表长度一样,两个链表再同时每次往后移一步,看节点是否一样,如果有相等的,说明这个相等的节点就是两链表的交点,否则如果走完了还没有找到相等的节点,说明他们没有交点,直接返回null即可

代码

/**
1.时间复杂度:O(M+N)
2.空间复杂度:O(1)
**/
class Solution
{
public:
    ListNode *FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
    {
        ListNode *p1 = pHead1, *p2 = pHead2;
        int l1 = 0, l2 = 0;
        while (p1) //求链表1的长度
        {
            p1 = p1->next;
            l1++;
        }
        while (p2) //求链表2的长度
        {
            p2 = p2->next;
            l2++;
        }
        p1 = pHead1;
        p2 = pHead2;
        //让p1为最长链表的头,l1为其长度
        if (l2 > l1)
        {
            swap(l1, l2);
            swap(p1, p2);
        }
        //求长度差
        int gap = l1 - l2;
        //让p1和p2在同一起点上
        while (gap--)
        {
            p1 = p1->next;
        }
        //遍历p1和p2,遇到相同则直接返回
        while (p1 != p2)
        {
            p1 = p1->next;
            p2 = p2->next;
        }
        return p1;
    }
};
posted @ 2021-01-13 10:52  RiverCold  阅读(73)  评论(0编辑  收藏  举报