Detecting Cycles in an Iterated Sequence
How to tell, using almost no extra memory, whether a sequence generated by repeatedly applying a function eventually loops back on itself — the tortoise-and-hare technique.
Prerequisites: Recursion and the Call Stack, How to Crack a What-Comes-Next Question
Define and , and ask: does this sequence ever repeat a value? With only 20 possible remainders, it must eventually repeat by pigeonhole — but where does the loop start, and how long is it? Storing every value you've seen and checking for repeats works, but it costs memory proportional to how far you go. There's a classic trick that finds the cycle using only two pointers and no memory of history at all.
The shape of an eventually-periodic sequence
Once a deterministic sequence repeats any value, it's trapped: from that point on it must retrace exactly the same steps forever, because always produces the same output from the same input. So the sequence looks like a "rho" shape — a straight run-in of length (the tail), followed by a loop of length (the cycle) that it circles forever after.
Floyd's cycle detection ("tortoise and hare")
Run two pointers through the sequence at different speeds: the tortoise moves one step per iteration, ; the hare moves two steps, . Both start at . Because the hare gains one extra step on the tortoise every iteration, and both are eventually confined to a loop of finite length , the hare is guaranteed to lap the tortoise and land on exactly the same value within one full loop — so if a cycle exists, the two pointers must meet. In plain English: imagine two runners on a circular track who never leave the track once they enter it — the faster one, going twice the speed, is bound to catch up to the slower one from behind, no matter where either started.
Worked example: tracing the sequence by hand
: , , . Already — the sequence hit 7 again after just one extra step, so the tail is alone () and the cycle is , length . Run the tortoise/hare check: tortoise at , hare at . Step 1: tortoise, hare (two steps: ). Not equal. Step 2: tortoise, hare (since , ). Tortoise is at 12, hare is at 12 — they meet, confirming a cycle exists, found in just two iterations without ever storing a list of past values.
What this means in practice
This exact two-pointer trick, at constant memory, is used to detect loops in linked-list-style structures generally, and the underlying pigeonhole reasoning — a process with finitely many states run forward indefinitely must repeat a state — is the same argument behind guaranteeing that a deterministic pseudo-random generator or a discretized mean-reverting process with finite precision eventually cycles.
A deterministic sequence over a finite set of possible values must eventually repeat, producing a tail followed by a cycle. Floyd's tortoise-and-hare algorithm finds this using two pointers moving at speeds 1 and 2, guaranteed to meet inside the cycle using only constant extra memory.
Practice in interviews
Further reading
- Knuth, The Art of Computer Programming, vol. 2, sec. 3.1