Fast & Slow Pointers Pattern
Two pointers, different speeds. One laps the other if the path loops.
Quick Summary
Best used when
- ✓You need to detect a cycle in a linked list or number sequence
- ✓You need to find the middle node of a linked list in a single pass
- ✓A visited-Set solution would work but costs too much space
- ✓The problem involves a sequence that might revisit a state
Clue words in the problem
Complexity gain
O(n) space visited-Set → O(1) space with pointer speed difference
Why this pattern matters for LeetCode
Cycle detection with a Set is intuitive: store every node you visit, check if the current node was already stored. But that costs O(n) space. Fast and slow pointers solve it in O(1) by using a physical insight: if two runners share the same loop, the faster one will eventually lap the slower one. They always meet inside the cycle, never outside. The same speed difference reveals the middle of a list with zero extra memory.
What the Fast & Slow Pointers pattern is
Fast and slow pointers (Floyd's Cycle Detection) uses two pointers that move at different speeds through the same sequence. Slow advances one step; fast advances two. If the sequence has no cycle, fast reaches the end first. If a cycle exists, fast eventually catches slow inside the loop and they land on the same node. Applied differently, the pattern finds the middle: when fast reaches the last node, slow is exactly at the midpoint.
Reach for Fast & Slow Pointers when you catch yourself thinking…
These are the internal questions that signal this pattern.
Beginner mental model
Picture two runners on a circular track. One runs at 1 lap/min, the other at 2 laps/min. If the track is a closed loop, the faster runner will lap the slower one no matter where they start. If the track is a dead-end road, the faster runner hits the wall first. That's your cycle check. For the middle: when the 2× runner finishes the whole track, the 1× runner has covered exactly half.
Ready to practice Fast & Slow Pointers?
Guided hints, not answers. You build real intuition.
When to use Fast & Slow Pointers
- ✓Detecting whether a linked list has a cycle (Linked List Cycle)
- ✓Finding the middle node in one pass (Middle of the Linked List)
- ✓Detecting repeated state in a number sequence (Happy Number)
- ✓Finding the start of a cycle once you've confirmed it exists (Floyd's full algorithm)
When NOT to use Fast & Slow Pointers
- ✕The sequence is an array where index arithmetic already finds the middle in O(1)
- ✕You need to record every visited node, not just detect a repeat
- ✕The structure is a tree — use recursive DFS or level-order BFS instead
- ✕You need the exact cycle length, not just its presence
Better alternative: In those cases a visited Set (O(n) space) works, or for trees use recursive traversal instead.
JavaScript code template
Cycle detection and middle node — O(n) time, O(1) space
// Cycle detection
function hasCycle(head) {
let slow = head;
let fast = head;
while (fast !== null && fast.next !== null) {
slow = slow.next; // one step
fast = fast.next.next; // two steps
if (slow === fast) return true;
}
return false; // fast hit null — no cycle
}
// Middle of the linked list
function middleNode(head) {
let slow = head;
let fast = head;
while (fast !== null && fast.next !== null) {
slow = slow.next;
fast = fast.next.next;
}
return slow; // fast is done, slow is at the middle
}Both variants share the same loop structure. Cycle detection returns true the moment slow === fast after a move. Middle-finding returns slow when the loop exits naturally. The guard `fast !== null && fast.next !== null` prevents null-pointer errors because fast moves two nodes per step and needs both to exist before moving.
Step-by-step thinking process
Walk through this in your head before writing code.
- 1Initialize both slow and fast to head.
- 2Loop while fast and fast.next are non-null.
- 3Advance slow one step and fast two steps.
- 4Cycle detection: after each move, check if slow === fast. If yes, there's a cycle.
- 5Middle finding: when the loop exits, slow is at the midpoint — return it.
- 6No cycle: if fast reaches null, return false.
“This app finally made it click. I tried NeetCode, CTCI, and YouTube for years and still couldn't solve Two Sum. The beginner mental models for the patterns are genuinely so helpful. THANK YOU.”
LeetCode-style problems that use this pattern
Practice on DSA Trainer with guided hints: no spoilers, just nudges.
- Linked List Cycle
The textbook fast/slow problem — detect a cycle in O(1) space without storing visited nodes.
Premium→ - Middle of the Linked List
When fast reaches the end, slow is exactly at the midpoint — the pattern's second core application.
Premium→ - Happy Number
Apply fast/slow to a digit-sum sequence — if it loops, fast and slow will meet on a repeated value.
Premium→
Coming soon
- Find the Duplicate NumberComing soon
Treat the array as an implicit linked list; Floyd's cycle detection finds the duplicate in O(1) space.
Common mistakes beginners make
- ✕Checking slow === fast before the first move — they both start at head so the check fires immediately. Move first, then compare.
- ✕Forgetting fast.next !== null in the guard — fast jumps two nodes, so both fast and fast.next must exist before the jump.
- ✕Using this on arrays — array index arithmetic gives you the middle in one operation. This pattern is for singly linked structures with no length field.
- ✕Confusing this with two-pointers — two-pointers typically starts at opposite ends and compares values; fast/slow starts at the same point and tracks position over time.
Fast & Slow Pointers vs Visited Set
Choose the right tool for the job.
| Pattern | Use when… |
|---|---|
| Fast & Slow Pointers | You only need to detect a cycle and O(1) space matters — you don't need to record every visited node |
| Visited Set | You need to find the exact node where the cycle starts, or you need a record of all visited states |
Time and space complexity
Time complexity
O(n)
Space complexity
O(1)
In a list with a cycle of length k, fast closes the gap by one step per iteration and catches slow within k steps after entering the cycle. Without a cycle, fast reaches null in at most n/2 iterations. Either way the loop runs O(n) times. Only two pointer variables are used — space is O(1) regardless of list length.
Ready to practice Fast & Slow Pointers?
Guided hints, not spoilers. 150 problems across 33 patterns. Five are free, the rest unlock with a founding member seat.
Frequently asked questions
- Why does fast always catch slow if there's a cycle?
- Once both pointers enter the cycle, fast gains on slow by exactly one step per iteration (fast moves 2, slow moves 1). The gap decreases by 1 each time. No matter what the initial gap is, it eventually reaches 0. They meet somewhere inside the cycle — the meeting point is guaranteed.
- How is this different from the Two Pointers pattern?
- Two Pointers typically starts at opposite ends of an array and moves inward, comparing values. Fast & Slow Pointers starts both at the same position and traverses the same structure at different speeds — it's about revealing structural properties (cycles, midpoints) rather than comparing values at two positions.
- Why does slow land at the middle when fast finishes?
- Fast moves at 2× the speed of slow. When fast has covered n nodes, slow has covered n/2 — exactly the midpoint. For even-length lists slow lands on the second of the two middle nodes, which is what LeetCode expects.
- Can I use this to find where a cycle starts?
- Yes, with a second phase. After the pointers meet, reset one to head. Move both one step at a time. The node where they meet again is the cycle's entry point. The proof uses modular arithmetic on the cycle length — it's Floyd's full algorithm.