思路:快慢指针
1.首先确定是否存在环,为了在O(1)时间内确定是否存在环,我们采取快慢指针的方式。
2.初始状态设置快指针fast=head,慢指针slow=head,然后快慢指针遍历整个链表,快指针每次比慢指针走快一步,这样每次多一步积累下去,如果存在环,那么快慢指针肯定会在环之内相遇,也就是slow==fast;如果不存在环,那么快指针肯定会提前走到链表尾部。
3.当确定已经存在环时,快慢指针停在环的某个位置,此时我们需要借组该位置确定环的初始位置,这时我们可以思考,是否可以使用快慢指针,在特殊起点开始遍历,控制遍历每一步的步长从而找到环的起始点,这里就需要采取数学猜想+演算方式了
4.先说解法,将快指针指向相遇点,慢指针指向起点,然后沿着链表一步步遍历,当两者再次相遇时,相遇点就是环起点。
5.证明网上有,这里给个很详细的参考链接
代码:
/**
* 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) {
if(!head)
return head;
ListNode* fast=head;
ListNode* slow=head;
int flag=0;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(slow==fast)
{
flag=1;
break;
}
}
if(!flag)
return NULL;
fast=slow;
slow=head;
while(fast!=slow)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
};