Sparround

Fast/slow pointers and cycle detection

Floyd's "tortoise and hare" rests on a single idea: two pointers start at the same place, one taking one step at a time, the other two.

The outcome has two properties:

  • If the chain is finite — the fast pointer reaches the end and never catches the slow one
  • If there is a cycle — the fast pointer enters the loop, laps around it, and is guaranteed to catch the slow one

Why guaranteed? Once both are inside the loop, the gap between them shrinks by exactly 1 every step (fast moves 2, slow moves 1). The gap is an integer and it decreases, so it must reach 0 — meaning they meet without jumping over each other. That explanation is valuable in an interview because it is a proof, not a recitation.

Complexity: O(n) time, `O(1)` memory — and the whole value of the pattern lies in that O(1).

The alternative — a hash set: collect visited nodes in a Set; hitting a node you've already seen means a cycle. Also O(n) time, but O(n) memory. In exchange the code is simpler and it gives you the start of the loop directly. The right tactic in an interview is to name both and justify the choice: "I'd start with the hash set because it's simpler; with a memory constraint I'd switch to Floyd."

Finding the start of the cycle is the part of Floyd's algorithm that looks magical, but simple arithmetic sits behind it.

The algorithm: after the pointers meet, send one back to the head, keep the other at the meeting point, and now move both one step at a time. They will meet exactly at the entrance of the loop.

Why: let a be the distance from the head to the loop entrance, b from the entrance to the meeting point, and c from the meeting point back round to the entrance (so the loop length is b + c).

  • The slow pointer has taken a + b steps
  • The fast one has taken twice as many, having lapped the loop k times: a + b + k(b + c) = 2(a + b)
  • Simplifying: a = k(b + c) − b = (k−1)(b + c) + c

Which says that the distance from the head to the entrance (`a`) equals the distance from the meeting point to the entrance (`c`) (whole laps don't change the difference). So one pointer from the head and one from the meeting point, moving at the same speed, meet at the entrance.

You aren't required to write the full derivation in an interview — but saying "it works out that a equals c, which is why it works" is the shortest way to distinguish yourself from someone reciting.

Finding the middle in one pass: the same technique, just without a cycle. When the fast pointer reaches the end, the slow one is at the middle. Note that an even-length list has two "middles" — the template above returns the second. For the first, change the loop condition to fast.next !== null && fast.next.next !== null. Asking about that detail in an interview ("which middle do you want on an even length?") shows care.

ProblemHow it appliesMemory
Does the linked list have a cycle?slow by 1, fast by 2; if they meet there is a cycleO(1)
Where does the cycle start?After meeting, send one back to the head and move both by 1O(1)
Middle of the list (one pass)when fast reaches the end, slow is in the middleO(1)
The k-th node from the endAdvance one pointer k steps first, then move both togetherO(1)
Happy-number style problemsA "next value" function forms an implicit linked list; a cycle means not happyO(1)
Find the duplicate number in an array (1..n)The mapping `i → a[i]` forms a graph; the duplicate is the cycle's startO(1) — without mutating the array
Is the linked list a palindrome?Find the middle, reverse the second half, compareO(1)

Interview tip: on a cycle-detection question, present both solutions and justify the choice — "Hash set: O(n) time, O(n) memory, five lines of code. Floyd: same time, O(1) memory, slightly subtle. With no memory constraint stated I'd start with the hash set and offer Floyd." The gap in scoring between a candidate with one solution and one who compares two is large. Second tip: never forget the guard fast !== null && fast.next !== null — without it fast.next.next blows up on null, and that is the most frequently caught mistake.