Grokking the Coding Interview: Patterns for Coding Questions
Vote

0% completed

​

Introduction to Fast & Slow Pointers Pattern

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:

  1. Create an empty hash set.
  2. Walk through the list.
  3. Add each node to the set.
  4. 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:

  1. Put both slow and fast at the head of the list.
  2. Check that fast and fast.next are not empty.
  3. Move slow forward by one node.
  4. Move fast forward by two nodes.
  5. If slow and fast point to the same node, return true.
  6. Repeat until the pointers meet or fast reaches the end.

If fast reaches the end, the list does not contain a cycle.

Slow moves one node and fast moves two, until both reach node 5 inside the loop.
Slow moves one node and fast moves two, until both reach node 5 inside the loop.

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 previous pointer 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

VariantWhat the two pointers provideProblems in this chapter
Cycle detectionthe pointers meet when a loop existsLinkedList Cycle, Happy Number, Cycle in a Circular Array
Find a positionslow reaches the middle when fast reaches the endMiddle of the LinkedList
Two phasesdetect a cycle, then find where the cycle startsStart of LinkedList Cycle
Split the listfind the middle, then compare or rearrange the two halvesPalindrome LinkedList, Rearrange a LinkedList

Learn cycle detection first. The other variants reuse the same pointer movement.

Watch out for

  • Checking fast.next before fast. Always confirm that fast exists first.
  • Comparing node values. Compare node identity because different nodes may store equal values.
  • Moving fast without checking both steps. The loop must check both fast and fast.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 next reference.

How this compares with nearby patterns

If the problem needs...Use...
a cycle or midpoint in a linked listFast and Slow Pointers
a pair or triplet in a sorted arrayTwo Pointers
a contiguous range in an array or stringSliding Window
links in a list reversed or reorderedIn-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

  • slow usually moves one step, and fast usually moves two steps.
  • If a cycle exists, the two pointers eventually meet.
  • If fast reaches the end, no cycle exists.
  • Check fast before fast.next.
  • Compare nodes, not only the values inside them.
  • The pattern takes O(N) time and O(1) extra space.

Now apply this pattern to LinkedList Cycle.

Reading Progress

0%


Vote for new content

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