0% completed
Introduction to Fast & Slow Pointers Pattern
On This Page
Core idea
How it works
Recognize it when
The template
Variants in this chapter
Watch out for
How this compares with nearby patterns
Key takeaways
You are given a linked list. Your task is to decide whether the list contains a cycle.
A linked list contains nodes. Each node has a value and a next reference to another node.
Normally, following next eventually reaches the end of the list. In a cycle, one node points back to an earlier node. Following next then continues forever.
A simple solution remembers every node that you visit:
- Create an empty hash set.
- Walk through the list.
- Add each node to the set.
- If a node is already in the set, the list has a cycle.
This solution takes O(N) time and O(N) extra space.
We can remove the hash set by using two pointers with different speeds.
Imagine two runners on a track. One runner moves one step at a time. The other moves two steps at a time.
If the track is a straight path, the faster runner reaches the end. If the track is a loop, the faster runner eventually catches the slower runner.
A linked list works in the same way. If the pointers meet at the same node, the list has a cycle.
Core idea
The Fast and Slow Pointers pattern moves two pointers through the same sequence at different speeds.
The slow pointer usually moves one step. The fast pointer usually moves two steps.
The pattern can detect a cycle or find a useful position, such as the middle of a linked list. It needs only a few variables.
This pattern is also called Floyd's Cycle Detection algorithm or the Tortoise and Hare algorithm.
How it works
Follow these steps to detect a cycle:
- Put both
slowandfastat the head of the list. - Check that
fastandfast.nextare not empty. - Move
slowforward by one node. - Move
fastforward by two nodes. - If
slowandfastpoint to the same node, returntrue. - Repeat until the pointers meet or
fastreaches the end.
If fast reaches the end, the list does not contain a cycle.
Why must the pointers meet inside a cycle?
After both pointers enter the cycle, fast gains one node on slow during every step. The distance between them becomes smaller around the loop. Eventually, that distance becomes zero.
Each pointer moves through at most a linear number of nodes. Therefore, the time complexity is O(N).
The algorithm stores only two pointers. Its extra space complexity is O(1).
Recognize it when
Fast and Slow Pointers may be useful when:
- The input is a linked list.
- The problem asks whether a cycle exists.
- The problem asks for the middle of a linked list.
- The input is a sequence where each value creates the next value.
- Your first solution stores every visited node in a hash set.
- The problem asks for constant extra space.
The Happy Number problem is an example of a generated sequence. Each number produces the next number. A repeating number creates a cycle.
Do not use this pattern when:
- You need a pair or triplet in a sorted array. Use Two Pointers.
- You need a contiguous part of an array or string. Use Sliding Window.
- You must reverse the links in a linked list. Use In-place Reversal of a Linked List.
- You only need the previous node while walking forward. One
previouspointer is simpler.
The template
function hasCycle(head): slow = head fast = head while fast is not empty and fast.next is not empty: slow = slow.next fast = fast.next.next if slow == fast: return true return false
Two details are important.
First, check fast before checking fast.next. If fast is empty, reading fast.next causes an error.
Second, compare the nodes themselves. Do not compare only their values. Two different nodes can contain the same value.
To find the middle of a list, use the same loop without the meeting test. When fast reaches the end, slow is near the middle.
Variants in this chapter
| Variant | What the two pointers provide | Problems in this chapter |
|---|---|---|
| Cycle detection | the pointers meet when a loop exists | LinkedList Cycle, Happy Number, Cycle in a Circular Array |
| Find a position | slow reaches the middle when fast reaches the end | Middle of the LinkedList |
| Two phases | detect a cycle, then find where the cycle starts | Start of LinkedList Cycle |
| Split the list | find the middle, then compare or rearrange the two halves | Palindrome LinkedList, Rearrange a LinkedList |
Learn cycle detection first. The other variants reuse the same pointer movement.
Watch out for
- Checking
fast.nextbeforefast. Always confirm thatfastexists first. - Comparing node values. Compare node identity because different nodes may store equal values.
- Moving
fastwithout checking both steps. The loop must check bothfastandfast.next. - Assuming the first meeting point starts the cycle. Finding the start requires a second phase.
- Ignoring even-length lists. Two middle nodes exist, so check which one the problem expects.
- Changing the structure by mistake. These pointers move through the list; they do not change any
nextreference.
How this compares with nearby patterns
| If the problem needs... | Use... |
|---|---|
| a cycle or midpoint in a linked list | Fast and Slow Pointers |
| a pair or triplet in a sorted array | Two Pointers |
| a contiguous range in an array or string | Sliding Window |
| links in a list reversed or reordered | In-place Reversal of a Linked List |
Both this pattern and Two Pointers use two positions. The rule for moving them is different.
In Two Pointers, values usually decide which pointer moves. In Fast and Slow Pointers, the two speeds are decided before the loop starts.
Key takeaways
slowusually moves one step, andfastusually moves two steps.- If a cycle exists, the two pointers eventually meet.
- If
fastreaches the end, no cycle exists. - Check
fastbeforefast.next. - Compare nodes, not only the values inside them.
- The pattern takes
O(N)time andO(1)extra space.
Now apply this pattern to LinkedList Cycle.
Reading Progress
0%
On This Page
Core idea
How it works
Recognize it when
The template
Variants in this chapter
Watch out for
How this compares with nearby patterns
Key takeaways