一.相关链接
视频链接:代码随想录:142.环形链表II
题目链接:142.环形链表II
二.心得体会
这道题是一道链表题,但他没有对头结点的操作,所以不用虚拟头结点。这道题要分两步进行,第一步是判断链表有没有环,这个只要让快慢指针同时从head出发,但fast每次走两步,slow每次走一步,最后如果fast能与slow相遇,那自然是有环链表,反之无环。
第二步是找到环的入口,这一步需要数学推导,我们知道fast走的总步数是slow的两倍,
即(x + y) * 2 = x + y + n (y + z),由此整理可知:x = (n - 1) (y + z) + z。其实意思就是如果要在入口处相遇,slow走过的x的长度就是fast在他们第一步在环内相遇点出发走了n-1圈后的长度,z就是他们第一步相遇后离入口的距离。看carl老师的图就一目了然了:
三.代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
int flag = 0; //记录有没有找到环的标记
//第一步,观察有没有环,如果有则记录下相遇点
while(fast!=NULL&&fast->next!=NULL){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
flag = 1;
slow = head;
break;
}
}
if(flag == 0) return NULL;
//第二步,找到环的入口
while(fast != slow){
slow = slow->next;
fast = fast->next;
}
return fast;
}
};