主要分为三步
第一步:快慢指针判断是否有环
第二步:上一步中slow和fast指针都在环上,我们让其中一个指针遍历环,当其第二次回到相遇点的时候,记录走过的步数就是环的长度。
第三步:定义两个指针,都指向首元结点,让其中一个先走n_cycle步,即一个环的长度,再让另一个指针走。当两个指针相遇的时候,先走的指针一共比后走的指针多走了n_cycle步,即一个环的长度,那么相遇点一定是入口。
/**
* 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 == NULL) return NULL;
ListNode *slow = head, *fast = head->next;
while(fast != NULL && fast->next != NULL){
if(slow == fast) break;
slow = slow->next;
fast = fast->next->next;
}
if(slow != fast) return NULL;
// 计算环的长度
int len = 1;
slow = slow->next;
while(slow != fast){
++len;
slow = slow->next;
}
// 让一个指针先走len步,然后另一个指针出发,再相遇则先出发指针比后出发指针多走了一个环,正好是入口
ListNode *temp1 = head, *temp2 = head;
while(len--){
temp1 = temp1->next;
}
while(temp1 != temp2){
temp1 = temp1->next;
temp2 = temp2->next;
}
return temp1;
}
};