我们使用快慢指针来解决这个问题。设环前路径为a,环长度为b
首先,尝试理解第一件事,当两个指针第一次相遇时,慢指针走过的路程是nb。
上述结论是可以推导的,设f,s分别为快,慢指针走过的路径,让二者同时出发,f = 2s,并且第一次相遇时 f = s + nb,联立可得出第一个结论、
接着来想第二件事,慢指针走多少步才能到入口点?答案是a+nb。第一次相遇时,慢指针已经走了nb了,所以再走a步即可。如何判断走了a步?让一个新指针和慢指针一起走,相遇即可。
上述方法不仅能求出入环点,还能得到a的大小。
代码中通过判断链表是否只有一个节点可以让快慢指针一起走再判断。
/**
* 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 || !head->next)return nullptr;
ListNode *slow = head, *fast = head, *tmp = head;
while(slow && fast)
{
fast = fast->next;
if(fast)fast = fast->next;
slow = slow->next;
if(slow == fast)break;
}
if(!fast)return nullptr;
while(tmp != slow)
{
slow = slow->next;
tmp = tmp->next;
}
return slow;
}
};