/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        if (!pHead || !pHead->next) return nullptr;
        ListNode *slow = pHead->next;
        ListNode *fast = pHead->next->next;
        while (fast && fast->next && fast != slow) {
            fast = fast->next->next;
            slow = slow->next;
        }
        if (!(fast && fast->next)) {
            return nullptr;
        }
        slow = pHead;
        while (fast != slow) {
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }
};

思路:先找是否有环。找到后fast在相遇位置,slow回退到pHead,然后两个指针相同速度遍历,相遇时即为环起点。后面的思路可能需要图,感觉手撕的话一般不会要求列等式计算。

设pHead到环起点距离为m,环起点到相遇点为k,环长度为n。相遇前慢节点在环里转了a圈,快节点转了b圈。

因为fast走过的路程是slow的两倍,有2 * (m + a * n + k) = m + b * n + k,化简得m = (b - 2 * a) * n - k。

慢节点从pHead继续出发,到环起始点距离为m;快节点以相同速度走m = (b - 2 * a) * n - k,再加上快节点原本距离环起始点为k,总共离环起始点的距离为(b - 2 * a) * n,即也在环起始点。