链表成环,在力扣中有这样的两道题目
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;
}