/**
* 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) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head==NULL)return NULL;
if(head->next==NULL)return NULL;
if(head->next->next==NULL)return NULL;
ListNode *pre = head->next;
ListNode *nxt = pre->next;
while(1){
if(pre==nxt)break;
if(pre->next==NULL)return NULL;
pre = pre->next;
if(nxt->next==NULL)return NULL;
nxt = nxt->next;
if(nxt->next==NULL)return NULL;
nxt = nxt->next;
}
pre = head;
while(pre!=nxt){
pre = pre->next;
nxt = nxt->next;
}
return pre;
}
};
对于判断链表是否有环,方法很简单,用两个指针,一开始都指向头结点,一个是快指针,一次走两步,一个是慢指针,一次只走一步,当两个指针重合时表示存在环了。
证明:假设链表有环,环的长度为N,慢指针在起始位置,快指针在位置k(位置从0开始计数),那么快指针只要比慢指针多走经过N-k步,就可以追上慢指针了。。。,因为每一次快指针都比慢指针多走一步,所以一定可以在有限的步数追上慢指针。
那么如何求环的起点呢:
1.假设我们的slow走了x步到达环的起点。
2.再走m步与fast汇合,那么这时,fast走的步数为2m+2x
3.同时fast在环中走的步数为2m+x;
4,所以可得2m+x=m+in(n为环的长度 )
所以可得m+x=in;
slow 移到head再走 x后。
注意:此时我们让fast指针也变成每次走一步
到达了开始,而此时fast的位置是2m+x+x
所以此时fast也走到了开始位置