Linked List Cycle II
Given the head of a linked list, return the node where the cycle begins. If there is no cycle, return null. Do not modify the linked list.
- The number of nodes in the list is in the range [0, 10⁴]
- -10⁵ <= Node.val <= 10⁵
- Do not modify the linked list
head = [3,2,0,-4], tail connects to index 1node at index 1 (value 2)head = [1,2], tail connects to index 0node at index 0 (value 1)head = [1], no cyclenullThis is the sequel to Linked List Cycle. There we only had to answer whether a loop exists; here we must return the exact node where the loop begins — the "door" you first walk through to enter the circle — or null if there is no loop. The list may not be modified. The naive fix is the same hash set as before: walk forward, and the first node you meet that's already in the set is the door. Correct, but O(N) extra memory. The beautiful part of this problem is that Floyd's two pointers find the door with no memory at all — and it comes for free once you understand one distance fact.
Run the identical fast/slow walk from Linked List Cycle. If fast hits a null, there's no loop — return null. Otherwise slow and fast collide somewhere inside the loop. That collision node is not the door in general (they meet wherever the speeds happen to line up). But its position hides exactly the information we need to walk to the door.
Give the three stretches names so we can add them up:
- F = number of steps from the head to the door (the straight part before the loop).
- a = number of steps from the door, going forward around the loop, to the meeting node.
- L = the length of the loop (one full trip around).
When they collide, slow has walked F + a steps. fast has walked the same ground plus some whole number of full laps around the loop — at least one — so fast walked F + a + (some laps). But fast also walked exactly twice as far as slow (it takes two steps for every one of slow's). Setting "twice slow" equal to "slow plus whole laps" and cancelling F + a from both sides leaves: F equals a whole number of laps minus a. In the simplest case of one lap, that's just F = L - a.
Read what that says in plain words: the distance from the head to the door (F) is the same as the distance from the meeting node, continuing forward around the loop, back to the door (L - a). Two different starting spots, the exact same number of steps to reach the same door. So: park one pointer at the head, leave the other at the meeting node, and step them both one at a time. After F steps each, they land on the door together. (The extra laps in the general case just mean the loop pointer circles a few more times before arriving — it still meets the head pointer precisely at the door.)
slow = fast = head
while fast and fast.next: # Phase one: same walk as Linked List Cycle
slow = slow.next
fast = fast.next.next
if slow == fast:
break
else:
return None # fast fell off the end → no loop
p = head # Phase two: one pointer from the head,
while p != slow: # the other left at the meeting node,
p = p.next # both moving one step at a time
slow = slow.next
return p # they meet exactly at the doorF = 0), the two pointers are already equal before the phase-two loop runs, so it returns the head immediately, which is correct. And we still compare nodes by identity, never by value.p on the head (node 3); leave the other pointer on node -4.p moves 3 → 2; the other moves -4 → (loops back) 2. Both are on node 2 — stop.The lesson to carry forward: same tool, sharper target. Cycle detection told us a loop exists; one extra distance fact turned the meeting point into a pointer to the loop's start. Whenever a fast/slow collision hands you a node, ask what that node's position secretly measures — often it's the key to the real answer.
Geometric Convergence Algorithm
Phase Details
Phase 1: Finding Collision
Use Slow (1x) and Fast (2x) pointers to detect the cycle. At Step 3, they collide at node 3.
We use a beautiful geometric symmetry. After the pointers first touch, the distance from the very start of the list to the entrance is exactly the same as the distance from the meeting spot to the entrance.
Most people use a "Seen nodes" list (Hash Set), but that takes extra memory. By using pure math and two pointers, we solve this with 0% extra space, which is the gold standard for top-tier coding interviews.
Time Complexity: O(N) | Space Complexity: O(1). The gold standard for detecting the start of a linked list cycle.