求两个链表的第一个公共结点(既求两条单链表的交点)

版权声明:本文为博主原创文章,欢迎转载,转载请声明出处! https://blog.csdn.net/hansionz/article/details/82717368

题目:输入两条单链表,求它们的第一个公共结点。结点的定义如下:

typedef struct Node
{
    DataType data;
    struct Node* next;
}Node,*pLinkList;

解题思路:

  • 方法一:暴力法。拿出一条链表中的一个结点,然后在另一条链表中从前向后扫描,如果存在相同的结点,则此节点为第一个公共结点,否则,继续向后遍历。假设两条链表的长度,一条为m,一条为n。这种方法的时间复杂度为O(m*n)

  • 方法二:借助栈的后进先出特点。两条单链表相交会有什么特点?它们相交后最后一个结点一定是同一个结点,可能是Y或者>,但是绝对不可能是X。既然是这样,我们能不能考虑从链表的最后,向前开始遍历呢?如果最后两条链表的最后一个结点相同,则继续向前找有没有相同的结点,如果没有,则这个结点就是第一个公共结点,如果有,则继续向前找。对于单链表,我们是没有办法从前向后遍历的,所以只能借助于栈,遍历两条链表,将他们分别压入一个栈,我们只要从栈顶开始比较即可。假设两条链表的长度,一条为m,一条为n。这种方法的时间复杂度为O(m+n),空间复杂度也是O(m+n),所以这是一种用空间换取时间的方法。

  • 方法三:快慢指针的思想。我们可以先求出两个链表的长度差,然后让长的那条链表先走长度差步,然后两条链表一起走,他们一定会在第一个公共结点处相遇。这种方法的时间复杂度为O(n+m),但是空间复杂度却为O(1)

由于前两种办法的时间复杂度或空间复杂度较高,面试官一般不会喜欢,所以这里只实现第三种方法:快慢指针的思想

代码实现:

//求两条链表的第一个公共结点
Node* GetMeetNode(pLinkList plist1, pLinkList plist2)
{
    int len1 = 0;
    int len2 = 0;
    int gap = 0;
    Node* cur1 = plist1;
    Node* cur2 = plist2;
    //求链表1长度
    while (cur1)
    {
        len1++;
        cur1 = cur1->next;
    }
    //求链表2长度
    while (cur2)
    {
        len2++;
        cur2 = cur2->next;
    }
    //求差值
    gap = abs(len1 - len2);

    cur1 = plist1;//长
    cur2 = plist2;//短
    if (len1 < len2)
    {
        cur1 = plist2;
        cur2 = plist1;
    }
    //较长链表先走gap步
    while (gap--)
    {
        cur1 = cur1->next;
    }
    //两个指针一起走一起走
    while (cur1!=cur2)
    {
        cur1 = cur1->next;
        cur2 = cur2->next;
    }
    return cur1;
}

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/82717368