👑个人主页:啊Q闻
🎇收录专栏:《数据结构》
🎉前路漫漫亦灿灿
前言
判断链表是否有环和返回链表入环后第一个节点这两道题目时相关联的,所以将两道题目放在一起来看看。这篇博客会详细分享一下两道题目的思路。
链表中是否有环
题目为:. - 力扣(LeetCode)
思路为:
定义快慢指针,快指针fast每次走两步,慢指针slow每次走一步,如果链表带环的话,快慢指针一定会在环内相遇。如果没有环,快指针会先走到空。
但是大家有没有这个疑问:
slow走一步,fast走两步,一定可以追上吗?
分析:fast先入环,过一段时间,slow也会入环,假设slow入环后,fast与slow之间的距离为 N,每追击一次,他们之间的距离就会缩小一步。
所以追击过程fast和slow的距离变化为:
N
N-1
N-2
N-3
……
0(当其变化为0时,代表其追上了)
slow走两步,fast走三步,可以追上吗?
分析:fast先入环,slow再入环,假设fast与slow之间的距离为N,每追击一次,他们之间的距 离就会缩小两步。
所以追击过程fast和slow的距离变化为:
N
N-2
N-4
N-6
……
当N为偶数时,为0,代表其可以追上
当N为奇数时,为-1,代表其错过了,两者会进行新一轮的追击,此时他们之间的距离变为C-1(C为环的长度),所以当C-1为偶数时,可以追上,当C-1为奇数时,则永远不可能追上。
那么,是否存在永远追不上的条件:N为奇数,C-1同时也为奇数呢?
分析:这里我们需要知道,快慢指针相遇是在入口点,第二道题目会有证明。
代码实现:
bool hasCycle(struct ListNode *head) {
struct ListNode*fast,*slow;
fast=slow=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)//环存在一定可以追上
{
return true;
}
}
return false;
}
返回链表入环后第一个节点
题目为:. - 力扣(LeetCode)
思路为:
定义快慢指针,两个指针会在入口点相遇,我们证明一下
证明一下:
代码实现:
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode*fast,*slow;
fast=slow=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)//相遇就代表有环
{
struct ListNode*meet=slow;
while(head!=meet)//在入口点相遇
{
meet=meet->next;
head=head->next;
}
return meet;
}
}
return NULL;
}
大家有没有感觉这两道代码比较麻烦的地方不是代码本身,而是其的推理逻辑呀,谢谢大家阅读,如果对你有帮助的话,三连支持一下吧