链表成环,在力扣中有这样的两道题目
https://leetcode.cn/problems/linked-list-cycle/
https://leetcode.cn/problems/linked-list-cycle-ii/description/
这道题的经典解法是利用快慢指针,如果链表是一个环形链表,那么快指针(fast)和慢指针(slow)一定会相遇,那为什么它们会相遇呢?此时的快慢指针之间的关系是fast=2*slow,如果换成fast=3*slow/4*slow? 还会相遇吗?
fast=2*slow推理如下 :
fast=3*slow推理如下 :
理解原理之后,再写代码就简单得多:
bool hasCycle(struct ListNode *head) {
struct ListNode*fast=head;
struct ListNode*slow=head;
while(fast&&fast->next)
{
//刚开始的时候,slow和fast在同一个节点,注意要先移动
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{
return true;
}
}
return false;
}
这题的进阶版
同样离不开快慢指针,记录下它们相遇的点,再让开始的节点和相遇点同时移动,再次相遇的就是环的起始位置,分析如下:
代码如下:
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode*fast=head,*slow=head;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
//记录相遇的点
if(fast==slow)
{
struct ListNode*meet=slow;
struct ListNode* cur=head;
//知道相遇
while(meet!=cur)
{
meet=meet->next;
cur=cur->next;
}
return meet;
}
}
return NULL;
}