0
点赞
收藏
分享

微信扫一扫

【Leetcode刷题笔记之链表篇】142. 环形链表 II

最不爱吃鱼 2022-01-20 阅读 46

😈博客主页:🐼大家好我叫张同学🐼
💖 欢迎点赞 👍 收藏 💗留言 📝 欢迎讨论! 👀
🎵本文由 【大家好我叫张同学】 原创,首发于 CSDN 🌟🌟🌟
精品专栏(不定时更新) 【数据结构+算法】 【做题笔记】【C语言编程学习】
☀️ 精品文章推荐
【C语言进阶学习笔记】三、字符串函数详解(1)(爆肝吐血整理,建议收藏!!!)
【C语言基础学习笔记】+【C语言进阶学习笔记】总结篇(坚持才有收获!)


前言
题目内容

在这里插入图片描述

原题链接(点击跳转)

思路分析
题目理解:这个题目应该拆分为两个问题:

要判断链表是否带环这个问题很简单,我们可以用快慢指针的方法,当fast在环内能追上slow即带环,当fast提前走到最后一个结点或NULL则表示不带环。(有关判断链表是否带环的问题在上一篇博客中已经详细的分析和证明了,不理解或有兴趣的同学可以前往我的主页翻看上一篇博客)
但当链表带环的时候要返回环的进入点这个问题却非常麻烦,要想解决这个问题,需要借助亿点点数学技巧。(不要害怕,是很基础的数学技巧,小学的时候就学过,只是一般人很难运用数学思维去分析。)
假设环进入点之前的链表长度为L,环的长度为Cslowfast两者的相遇点与环的进入点之间的距离为X,如下图所示:
在这里插入图片描述
slow、fast开始走到两者相遇的整个过程中
slow走过的长度为:L+X
fast走过的长度为:L+nC+X(注意,fast不一定只是在环里面转了一圈,有可能转了2、3、4...n圈,n >= 1
在这里插入图片描述
因为slow一次走一步,fast一次走两步,所以fast走过的长度是slow的两倍,也就是:
L+nC+X = 2(L+X)等式两边消掉一个L+X,再将右边的X移到左边去即有:
nC-X = L 为了符合我们的阅读习惯,我们将左右换一下,也就是:
L = nC-X = (n-1)C + C-XC-X是环的长度 - 相遇点到进入点之间的长度,也就是下面这个长度:
在这里插入图片描述
也就是说链表的长度L = n-1圈的环长度 + C - X。如果我们让两个点,一个从链表起始点走,一个从相遇点meet位置走,均是每次走一步,那么这两个点必定会在环的进入点相遇。
仔细理解一下上面这句话,因为链表的长度L = (n-1)C + C - X, (n >= 1),当n=1的时候,表示两个点直接走着走着就在环入口点相遇了。(比如说你和女朋友约好去操场散步,你女朋友到操场门口的距离是L,你到操场的距离是C-X,操场的周长为C。这种情况就是你俩同时出门,一起走向操场门口,然后一起到达门口,手拉手去散步)
n >1时,从meet出发的点则会先在环里面转上 n - 1圈,然后两者在环入口点相遇(这种情况就是你女朋友离操场比较远,L比较大,虽然你俩同时往操场走,但是你先到达,你到达后没事干就在操场里面溜达几圈,然后和你女朋友在操场门口相遇)。
理解了 L = (n-1)C + C - X, (n >= 1),要写出代码,完成题目就很简单了。

函数实现
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast = head,*slow = head;
    while(fast && fast->next){
        slow = slow->next;
        fast = fast->next->next;
        if(fast == slow){
            struct ListNode *meet = slow,*cur = head;
            while(meet != cur){
                meet = meet->next;
                cur = cur->next;
            }
            return meet;
        }
    }
    return NULL;
}

在这里插入图片描述


思路分析

除了用上面的数学等式来解决外,我们还可以使用另一种方法来解决。只是这种方法在写代码的时候会比较麻烦。
假设slowfast相遇的位置为meet,将链表从相遇点meet断开,这时候就将求环进入点的问题,转化为求链表相交求交点的问题了。
在这里插入图片描述

函数实现
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *pA = headA, *pB = headB;
    while (pA != pB) {
        pA = pA == NULL ? headB : pA->next;
        pB = pB == NULL ? headA : pB->next;
    }
    return pA;
}

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast = head,*slow = head;
    while(fast && fast->next){
        slow = slow->next;
        fast = fast->next->next;
        if(fast == slow){
            struct ListNode *meet = slow,*next = slow->next,*cur = head;
            meet->next = NULL;
            return getIntersectionNode(cur,next);
        }
    }
    return NULL;
}

在这里插入图片描述

举报

相关推荐

0 条评论