Algorithm

Linked List Cycle II

Two Pointer Pattern

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.

CONSTRAINTS
  • The number of nodes in the list is in the range [0, 10⁴]
  • -10⁵ <= Node.val <= 10⁵
  • Do not modify the linked list
EXAMPLE 1
Input: head = [3,2,0,-4], tail connects to index 1
Output: node at index 1 (value 2)
The last node (-4) links back to the node at index 1, so the loop begins at that node. That node is returned.
EXAMPLE 2
Input: head = [1,2], tail connects to index 0
Output: node at index 0 (value 1)
The loop starts at the head itself, so the head node is the entrance and is returned.
EXAMPLE 3
Input: head = [1], no cycle
Output: null
There is no loop, so there is no entrance node to return.
Return the node, its index, or its value?
Return the node object where the cycle starts. In the no-cycle case return null.
Is a cycle guaranteed to exist?
No — the list may be a plain straight list. Your solution must return null when the fast pointer reaches the end without a collision.
Can I modify the list, for instance to mark nodes?
No — the statement forbids modifying the list. The two-pointer method needs no modification and no extra memory.

This 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.

Step one is a problem you've already solved

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.

The one distance fact that cracks it open

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.)

python
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 door
Crucial Notein phase two both pointers move at the same speed, one step each — this is no longer the double-speed walk. If the loop starts right at the head (F = 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.
Worked Example:head = [3, 2, 0, -4], node -4 points back to node 2
- Phase one: slow and fast run the double-speed walk and collide on node -4.
- Phase two: put p on the head (node 3); leave the other pointer on node -4.
- One step each: p moves 3 → 2; the other moves -4 → (loops back) 2. Both are on node 2 — stop.
- Return node 2, the door where the cycle begins.

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.

Interactive Strategy Visualization
CYCLE ORIGIN TRACKER

Geometric Convergence Algorithm

H
1
2
3
ENTRANCE
4
5
MEET
FAST
CYCLE DETECTED

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.

Finding the Doorway

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.

Zero Extra Space

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.

Strategy: Floyd's Tortoise and Hare

Time Complexity: O(N) | Space Complexity: O(1). The gold standard for detecting the start of a linked list cycle.

O(N) Time · O(N) Space Hash Set
O(N) Time · O(1) Space Two-Phase Fast/Slow