What is the fast and slow pointer pattern, and which problems does it solve?
The pattern is two pointers that travel through the same structure at different rates. The slow pointer moves one step at a time and the fast pointer moves two. Every problem that asks something about the structure of a list or a sequence becomes tractable, because the difference between the two positions is a function of the distance travelled.
class Node:
def __init__(self, value, next_node=None):
self.value = value
self.next = next_node
def has_cycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
return False
head = Node(1)
head.next = Node(2)
head.next.next = head
print(has_cycle(head))The output is True. The third node points back to the first, so the list loops and the two pointers eventually land on the same node.
The three classics are cycle detection, where the pointers eventually meet because the fast one laps the slow one; finding the middle, where the fast one reaches the end at exactly twice the distance the slow one has covered; and finding the cycle entry point, which follows from cycle detection with a second phase.
The mechanism is the growing gap. After k steps the fast pointer has travelled two k nodes and the slow one k, so the gap is k. If the structure is finite and looping, that gap eventually becomes a whole number of laps and the pointers coincide. If the structure is a finite list, the fast pointer simply runs out first.
The trade-off to name is space against passes. The pattern uses a constant amount of extra memory and often a single pass, whereas the straightforward alternatives either use a hash set with linear space or make two passes over the data. What it costs is readability: every loop condition has to check the fast pointer and its successor, because advancing two steps requires two nodes to exist, and that detail is where most bugs in this family live.