給定單鏈表頭節點,判斷是否有環,若有返回環入口節點,否則返回 null。要求 O(1) 空間。
fast 每次走 2 步,慢指針 slow 每次走 1 步。若有環,必相遇。設頭節點到環入口距離 a,環入口到相遇點距離 b,環長度 L。相遇時:
slow 路程 = a + b
fast 路程 = a + b + kL = 2(a+b) ⇒ a + b = kL ⇒ a = kL - b。
即:從頭節點走 a 步到入口,從相遇點繼續走 a 步(即 kL - b)也到入口。
ListNode* detectCycle(ListNode* head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) break;
}
if (!fast || !fast->next) return nullptr; // 無環
fast = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow; // 入口節點
}
head->next = head,算法正常工作。O(n):第一階段 ≤ n 步相遇,第二階段 ≤ a 步。O(1):僅兩指針。