Leetcode刷题笔记之链表篇142. 环形链表 II
Posted 大家好我叫张同学
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode刷题笔记之链表篇142. 环形链表 II相关的知识,希望对你有一定的参考价值。
😈博客主页:🐼大家好我叫张同学🐼
💖 欢迎点赞 👍 收藏 💗留言 📝 欢迎讨论! 👀
🎵本文由 【大家好我叫张同学】 原创,首发于 CSDN 🌟🌟🌟
✨精品专栏(不定时更新) 【数据结构+算法】 【做题笔记】【C语言编程学习】
☀️ 精品文章推荐
【C语言进阶学习笔记】三、字符串函数详解(1)(爆肝吐血整理,建议收藏!!!)
【C语言基础学习笔记】+【C语言进阶学习笔记】总结篇(坚持才有收获!)
前言 |
为什么要写
刷题笔记
?
写博客
的过程也是对自己刷题过程的梳理
和总结
,是一种耗时
但有效
的方法。
当自己分享的博客帮助到他人时,又会给自己带来额外的快乐和幸福。
(刷题的快乐+博客的快乐,简直是奖励翻倍,快乐翻倍
有木有QAQ🙈)
题目内容 |
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪next
指针再次到达,则链表中存在环。
为了表示给定链表中的环,评测系统内部使用整数pos
来表示链表尾连接到链表中的位置(索引从0
开始)。如果 pos 是-1
,则在该链表中没有环。
注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改
链表。
思路分析 |
①判断链表是否带环
②当链表带环的时候返回环的进入点
要判断链表是否带环这个问题很简单,我们可以用快慢指针的方法,当fast
在环内能追上slow
即带环,当fast提前走到最后一个结点或NULL
则表示不带环。(有关判断链表是否带环的问题在上一篇博客中已经详细的分析和证明了,不理解或有兴趣的同学可以前往我的主页翻看上一篇博客)
但当链表带环的时候要返回环的进入点这个问题却非常麻烦,要想解决这个问题,需要借助亿点点数学技巧
。(不要害怕,是很基础的数学技巧,小学的时候就学过,只是一般人很难运用数学思维去分析。)
假设环进入点之前的链表长度为L
,环的长度为C
,slow
与fast
两者的相遇点
与环的进入点
之间的距离为X
,如下图所示:
从slow、fast
开始走到两者相遇的整个过程中
slow
走过的长度为:L+X
fast
走过的长度为:L+nC+X
(注意,fas
t不一定只是在环里面转了一圈,有可能转了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-X
。C-X
是环的长度 - 相遇点到进入点之间的长度,也就是下面这个长度:
也就是说链表的长度L = n-1圈的环长度 + C - X
。如果我们让两个点,一个从链表起始点走,一个从相遇点mee
t位置走,均是每次走一步
,那么这两个点必定会在环的进入点相遇。
仔细理解一下上面这句话,因为链表的长度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;
思路分析 |
除了用上面的数学等式来解决外,我们还可以使用另一种方法来解决。只是这种方法在写代码的时候会比较麻烦。
假设slow
和fast
相遇的位置为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;
以上是关于Leetcode刷题笔记之链表篇142. 环形链表 II的主要内容,如果未能解决你的问题,请参考以下文章