Floyd's Cycle Detection
Imagine two runners on a circular track. One runs at normal speed, the other runs twice as fast. If they start together, will the fast runner ever lap the slow one and meet them again? Yes — always, and relatively quickly.
Now imagine the track is a linked list with a cycle (a loop in the chain). A slow pointer moves one node at a time. A fast pointer moves two nodes at a time. If a cycle exists, the fast pointer will eventually lap the slow pointer and they will point to the same node. If there's no cycle, the fast pointer will reach the end of the list (null) first.
This is Floyd's Cycle Detection Algorithm — also called the tortoise and the hare. It solves a problem that sounds expensive in \(O(1)\) space, with no hash sets, no visited arrays, nothing but two pointer variables.
← → arrow keys to step · click elements to interact
Floyd's Cycle Detection
Phase 1: Does a cycle exist?
Why does this work? If there's a cycle of length k, the fast pointer enters the cycle and laps the slow pointer. The gap between them closes by 1 each step (fast gains 1 node per step on slow), so they must meet within k steps after both enter the cycle. Total steps: \(O(n)\).
Phase 2: Where does the cycle start?
Once you've detected the meeting point, you can find the exact node where the cycle begins with a elegant mathematical trick:
- Keep one pointer at the meeting point.
- Move the other pointer back to
head. - Advance both pointers one step at a time.
- Where they meet is the start of the cycle.
Why? Let F = distance from head to cycle start, a = distance from cycle start to meeting point (inside cycle), C = cycle length. At the meeting point, slow has traveled F + a steps. Fast has traveled F + a + nC (full extra laps). Since fast moves twice as fast: 2(F + a) = F + a + nC, which simplifies to F = nC − a. Moving one pointer from head and one from the meeting point at the same speed, they both arrive at the cycle start after exactly F steps.
Why not use a hash set instead?
You could detect a cycle by storing every visited node in a hash set and checking if you've seen the current node before. That works, but costs \(O(n)\) extra space. Floyd's algorithm solves the same problem with \(O(1)\) space — just two pointer variables. For large lists, this is a meaningful difference.
Where does this appear in practice?
- Interview problems — LeetCode 141 (has cycle) and 142 (find cycle start) are classic problems directly using this algorithm.
- Detecting infinite loops in custom iterators or generators.
- Finding the duplicate number — a clever problem (LeetCode 287) models an array as a linked list and applies Floyd's to find the repeated value in \(O(n)\) time, \(O(1)\) space.
- Rho algorithm for integer factorization uses the same cycle-detection idea.