• 相交链表+判断环型链表+求环型链表的入口节点


    一.相交链表

    相交链表

    在这里插入图片描述

    相交:两个链表从头开始遍历,尾节点一定是同一个节点。

    情况一:当两个链表长度相同时:
    在这里插入图片描述

    情况二:当两个链表长度不同时:

    在这里插入图片描述
    思路:

    1. 求两个链表长度的差值gap。
    2. 让长链表先走gap个节点。
    3. 分别遍历两个链表,比较是否为同一个节点,若是则相交,否则不相交。

    代码如下:

    typedef struct ListNode ListNode;
    
    struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
    {
        ListNode* la = headA;
        ListNode* lb = headB;
        int lengthA = 0, lengthB = 0;
        while(la)
        {
            lengthA++;//求链表A的长度
            la = la->next;
        }
        while(lb)
        {
            lengthB++;//求链表B的长度
            lb = lb->next;
        }
        //求链表A与链表B长度差的绝对值
        int gap = abs(lengthA - lengthB);
    
        //找出长链表与短链表
        ListNode* longList = headA;
        ListNode* shortList = headB;
        if(lengthB > lengthA)
        {
            longList = headB;
            shortList = headA;
        }
    
        //让长链表先走gap个节点
        while(gap--)
        {
            longList = longList->next;
        }
    
        //此时longList与shortList指针在相对的位置上(同时遍历链表为NULL)
        //判断两个链表是否相交
        while(longList && shortList)
        {
            if(longList == shortList)
            {
                //链表相交
                return longList;
            }
            //两个指针继续往后走
            longList = longList->next;
            shortList = shortList->next;
        }
        //链表不相交
        return NULL;
    }
    

    二.判断环型链表

    环型链表

    在这里插入图片描述

    思路:快慢指针,即慢指针一次⾛一步,快指针一次走两步,两个指针从链表起始位置开始行,如果链表带环则一定会在环中相遇,否则快指针率先走到链表的未尾。

    思考1:为什么快指针每次走两步,慢指针走一步可以相遇,有没有可能遇不上,请推理证明!
    在这里插入图片描述

    因此,在带环链表中慢指针走一步,快指针走两步最终一定会相遇。

    思考2:快指针一次走3步,走4步,…n步行吗?

    在这里插入图片描述
    在这里插入图片描述

    思考:真的存在N是奇数,C是偶数这一条件???

    下面给出等式:
    在这里插入图片描述

    在这里插入图片描述

    代码如下:

    1. 慢指针一次走一步,快指针一次走两步
    typedef struct ListNode ListNode;
    
    bool hasCycle(struct ListNode* head)
    {
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast && fast->next)
        {
            //慢指针一次走一步,快指针一次走两步
            slow = slow->next;
            fast = fast->next->next;
            //当慢指针 == 快指针时,有环
            if (slow == fast)
            {
                return true;
            }
        }
        //无环
        return false;
    }
    
    1. 慢指针一次走一步,快指针一次走三步:
    typedef struct ListNode ListNode;
    
    bool hasCycle(struct ListNode *head) 
    {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast && fast->next && fast->next->next)
        {
            //慢指针一次走一步,快指针一次走三步
            slow = slow->next;
            fast = fast->next->next->next;
            //当慢指针 == 快指针时,有环
            if(slow == fast)
            {
                return true;
            }
        }
        //无环
        return false;
    }
    

    三.求环型链表的入口节点

    环型链表 ||

    在这里插入图片描述

    思路:快慢指针,快指针一次走两步,慢指针一次走一步,若为环型链表最终在环中相遇,然后让一个指针从相遇点开始走,一个指针从起点开始走,一次走一步,最终在进环处相遇。

    在这里插入图片描述

    代码如下:

    //解:快慢指针,快指针一次走两步,慢指针一次走一步,若为环型链表最终在环中相遇
     //    然后让一个指针从相遇点开始走,一个指针从起点开始走,一次走一步,最终在进环处相遇
    
    typedef struct ListNode ListNode;
    
    struct ListNode* detectCycle(struct ListNode* head)
    {
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast)
            {
                //有环
                ListNode* meet = slow;//相遇点
                while (meet != head)
                {
                    //一个指针从相遇点开始走,一个指针从起点开始走,最终一定在入环点相遇
                    head = head->next;
                    meet = meet->next;
                }
                return meet;//入环点
            }
        }
        return NULL;//无环
    }
    

    在这里插入图片描述

    typedef struct ListNode ListNode;
    
    struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
    {
        ListNode* la = headA;
        ListNode* lb = headB;
        int lengthA = 0, lengthB = 0;
        while(la)
        {
            lengthA++;//求链表A的长度
            la = la->next;
        }
        while(lb)
        {
            lengthB++;//求链表B的长度
            lb = lb->next;
        }
        //求链表A与链表B长度差的绝对值
        int gap = abs(lengthA - lengthB);
    
        //找出长链表与短链表
        ListNode* longList = headA;
        ListNode* shortList = headB;
        if(lengthB > lengthA)
        {
            longList = headB;
            shortList = headA;
        }
    
        //让长链表先走gap个节点
        while(gap--)
        {
            longList = longList->next;
        }
    
        //此时longList与shortList指针在相对的位置上(同时遍历链表为NULL)
        //判断两个链表是否相交
        while(longList && shortList)
        {
            if(longList == shortList)
            {
                //链表相交
                return longList;
            }
            //两个指针继续往后走
            longList = longList->next;
            shortList = shortList->next;
        }
        //链表不相交
        return NULL;
    }
    
    struct ListNode *detectCycle(struct ListNode *head) 
    {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast)
            {
                //有环
                ListNode* meet = slow;//相遇点
                ListNode* newHead = meet->next;
                meet->next = NULL;
    
                return getIntersectionNode(head, newHead); 
            }
        }
        return NULL;//无环
    }
    
  • 相关阅读:
    2022.8.18-8.19 代码记录
    【241. 为运算表达式设计优先级】
    Retrofit 帮助 OKHttp 解决了多少问题?
    自然辩证法2023年预测考点
    没有 SegWit 和 Taproot 的比特币序数
    防止血糖飙升,你需要知道这12个技巧
    【区块链技术与应用】(三)
    数据结构——单调栈
    【Modbus通信实验五】常见问题汇总
    Pandas中的方法及使用示例
  • 原文地址:https://blog.csdn.net/2203_76003626/article/details/140430055