[LeetCode]相交链表

[LeetCode]相交链表

  • 题目
  • 分析
  • 代码
  • 总结


题目

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。图示两个链表在节点 c1 开始相交:
[LeetCode]相交链表_第1张图片
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。

[LeetCode]相交链表_第2张图片

链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/description/


分析

我们在拿到这道题目时,我们的第一反应一一遍历两个链表,只要两个指针指向的元素地址相同我们就找到了两个链表相交的结点。

但我们现在面临一个问题,我们在创建两个指针分别指向两个链表遍历时,因为每个链表的长度可能不一样,那么我们就可能会造成就算两个链表相连,我们两个指针在遍历的时候也不可能相遇

那么我们应该然后解决这个问题呢?

那么这个时候我们可以采用这种解决方法来实现,我们想分别计算出每个链表的长度,然后我们计算两个链表长度的差值,我们让较长链表的指针先向后移动差值的单位距离,之后我们在同时遍历我们的两个链表,当我们的两个指针指向的节点地址相同时,我们就找到了相交的节点。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
     

    struct ListNode* n1 = headA;
    struct ListNode* n2 = headB;
    int l1 = 0;
    int l2 = 0;
    int gap = 0;

    while(n1)//计算我们第一个链表的长度
    {
     
        l1++;
        n1 = n1->next;
    }
    while(n2)//计算我们第二个链表的长度
    {
     
        l2++;
        n2 = n2->next;
    }

    if(l1 > l2)//判读那个链表长,然后将长的链表移动长度的差值
    {
     
        gap = l1 - l2;
        while(gap--)
        {
     
            n1 = n1->next;
        }
    }

    if(l2 > l1)
    {
     
        gap = l2 - l1;
        while(gap--)
        {
     
            n2 = n2->next;
        }
    }
    while(n1 && n2)//开始同时遍历我们的链表
    {
     
        if(n1 == n2)
        {
     
            return n1;
        }
        else
        {
     
            n1 = n1->next;
            n2 = n2->next;
        }
    }
    return NULL;
    
}

[LeetCode]相交链表_第3张图片

这个时候我们看似实现了我们的题目要求,可当我们运行代码时,我们得出
[LeetCode]相交链表_第4张图片
这里提醒我们有空值的出现,使得在移动长链表时移动失败,这个时候我们回看代码,发现我们在前面获取两个链表的长度时,已经将两个链表的指针移动到了最后一个节点的位置,所以会提醒我们会有空值的情况出现

这个时候我们可以在创建两个指针再一次指向我们的两个链表,创建时间为当我们得出两个链表的长度后,我们再创建这两个指针,然后我们开始后续的操作

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
     

    struct ListNode* n1 = headA;
    struct ListNode* n2 = headB;
    int l1 = 0;
    int l2 = 0;
    int gap = 0;

    while(n1)
    {
     
        l1++;
        n1 = n1->next;
    }
    while(n2)
    {
     
        l2++;
        n2 = n2->next;
    }

    struct ListNode* nn1 = headA;
    struct ListNode* nn2 = headB;

    if(l1 > l2)
    {
     
        gap = l1 - l2;
        while(gap--)
        {
     
            nn1 = nn1->next;
        }
    }

    if(l2 > l1)
    {
     
        gap = l2 - l1;
        while(gap--)
        {
     
            nn2 = nn2->next;
        }
    }
    while(nn1 && nn2)
    {
     
        if(nn1 == nn2)
        {
     
            return nn1;
        }
        else
        {
     
            nn1 = nn1->next;
            nn2 = nn2->next;
        }
    }
    return NULL;
    
}

我们将代码优化一下,使代码的可读性更强一些(我们将代码中指针的创建命名更易懂)

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
     
    struct ListNode* curA = headA;
    struct ListNode* curB = headB;
    int lenA = 0,lenB = 0;

    while(curA)
    {
     
        lenA++;
        curA = curA->next;
    }
     while(curB)
    {
     
        lenB++;
        curB = curB->next;
    }

    struct ListNode * ListLong = headA;
    struct ListNode * ListShort = headB;
    if(lenA < lenB)
    {
     
        ListLong = headB;
        ListShort = headA;
    }

    int gap = abs(lenA - lenB);

    while(gap--)
    {
     
        ListLong = ListLong -> next;
    }

    while(ListLong && ListShort)
    {
     
        if(ListLong == ListShort)
        {
     
            return ListLong;
        }
        else
        {
     
            ListLong = ListLong -> next;
            ListShort = ListShort -> next;
        }
    }
    return NULL;
}

代码

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
     
    struct ListNode* curA = headA;
    struct ListNode* curB = headB;
    int lenA = 0,lenB = 0;

    while(curA)
    {
     
        lenA++;
        curA = curA->next;
    }
     while(curB)
    {
     
        lenB++;
        curB = curB->next;
    }

    struct ListNode * ListLong = headA;
    struct ListNode * ListShort = headB;
    if(lenA < lenB)
    {
     
        ListLong = headB;
        ListShort = headA;
    }

    int gap = abs(lenA - lenB);

    while(gap--)
    {
     
        ListLong = ListLong -> next;
    }

    while(ListLong && ListShort)
    {
     
        if(ListLong == ListShort)
        {
     
            return ListLong;
        }
        else
        {
     
            ListLong = ListLong -> next;
            ListShort = ListShort -> next;
        }
    }
    return NULL;
}

总结

链表相交问题中,我们在计算两个链表的长度时,指针已经指向里链表的最后一个元素,而我们如果再继续执行后面的代码,那么我们就会造成本题中出现的空值问题,这一点需要以后在解决问题中多加注意

以上就是我对这道题目的个人理解

上述内容如果有错误的地方,还麻烦各位大佬指教【膜拜各位了】【膜拜各位了】
在这里插入图片描述

你可能感兴趣的:(LeetCode刷题,链表,leetcode,算法,数据结构,C语言)