AlgoPlusAlgoPlus
Learn/Problem-Solving Patterns
Lesson

Fast & Slow Pointers

Floyd's tortoise and hare: two pointers at different speeds detect a cycle in a linked structure using constant memory.

7 min read Watch it move Build it

The fast and slow pointers technique — also called Floyd's tortoise and hare — detects a loop in a linked structure using two pointers that start together and move at different speeds. The slow pointer steps 1 node at a time; the fast pointer steps 2. If the path eventually loops, the fast pointer circles around and catches the slow one from behind. If there's no loop, the fast pointer simply runs off the end.

Why the fast pointer must catch the slow one

Once both pointers are inside the cycle, think about the gap between them. Each step, the fast pointer gains exactly one node on the slow pointer (it moves 2, the slow moves 1). A gap that shrinks by one every step must eventually hit zero — so they land on the same node. The fast pointer can never 'jump over' the slow one, because a lead of one closing to zero means they meet.

Constant memory is the win
Marking visited nodes in a hash set also detects a cycle, but costs O(n) extra space. The tortoise and hare need only two pointers — O(1) space — no matter how large the structure.

The steps

  1. 1Start both slow and fast at the head.
  2. 2Each iteration: move slow one step, move fast two steps.
  3. 3If slow === fast, they met inside a loop → a cycle exists.
  4. 4If fast reaches the end (null), the path terminates → no cycle.

Worked trace — 1 → 2 → 3 → 4 → 5, with 5 linking back to 3

  1. 1Start: slow at 1, fast at 1.
  2. 2Step 1: slow → 2; fast → 3 (via 2). Not equal.
  3. 3Step 2: slow → 3; fast → 5 (via 4). Not equal.
  4. 4Step 3: slow → 4; fast → 4 (5 → 3 → 4). Equal — cycle detected.
Guard the fast pointer
Because fast reads fast.next.next, you must check both fast and fast.next are non-null before stepping — otherwise a list with no cycle crashes on a null dereference.
function hasCycle(head) {
  let slow = head, fast = head;
  while (fast && fast.next) {
    slow = slow.next;        // 1 step
    fast = fast.next.next;   // 2 steps
    if (slow === fast) return true; // they met
  }
  return false; // fast ran off the end
}
OperationTimeSpace
Cycle detection · two pointers, no extra structureO(n)O(1)
Check yourself
Once both pointers are in the cycle, why are they guaranteed to meet?