题目:https://leetcode-cn.com/problems/linked-list-cycle-ii/ 题解:假设该表是环形链表,链式部分长度为 a a a,环形部分长度为 b b b。定义快指针 f a s t fast fast和慢指针 s l o w slow slow,先让 f a s t fast fast每次走两步, s l o w slow slow每次走一步,直到两者相遇;接着让 f a s t fast fast重置回头结点, f a s t fast fast和 s l o w slow slow都每次走一步,可以证明 f a s t fast fast走 a a a步后刚好和 s l o w slow slow相遇。 假设第一次 s l o w slow slow走了 ( a + k ) (a+k) (a+k)步,那么 f a s t fast fast走了 ( a ∗ 2 + k ∗ 2 ) (a*2+k*2) (a∗2+k∗2)步,且有 ( a + 2 ∗ k ) % b = = k % b (a+2*k)\%b==k\%b (a+2∗k)%b==k%b;接着 f a s t fast fast从头开始,走 a a a步后,刚进入环形圈,要证明 s l o w slow slow也刚好走到环形圈起点,即证 ( a + k ) % b = = 0 (a+k)\%b==0 (a+k)%b==0。在式子 ( a + 2 ∗ k ) % b = = k % b (a+2*k)\%b==k\%b (a+2∗k)%b==k%b两边减去 k k k,得证。
/**
* 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) {
/*
*给定一个链表,返回链表开始入环的第一个节点。
*如果链表无环,则返回 null
*/
ListNode *fast = head;
ListNode *slow = head;
if(head == nullptr) return nullptr;
do{
if(fast->next == nullptr || fast->next->next == nullptr)
return nullptr;
fast = fast->next->next;
slow = slow->next;
}while(fast != slow);
fast = head;
while(fast != slow) {
fast = fast->next;
slow = slow->next;
}
return slow;
}
};