Fast & Slow Pointers, Gaps and Merging
Find the middle, detect cycles, locate the nth node from the end, and merge or split lists.
14 min, 0 of 3 activities solved
View cheatsheetGetting Python ready… examples can run in a moment.
You can't ask a linked list for its length or its middle, but two pointers moving at different speeds answer both in one pass with O(1) space.
Fast & slow. slow moves one step, fast
moves two. When fast reaches the end, slow has
covered half the distance, so it's at the middle:
1 -> 2 -> 3 -> 4 -> 5
s,f
s f
s f (fast.next is None: stop)
With an even length there are two middles. The loop
while fast and fast.next lands on the second
one; while fast.next and fast.next.next lands on
the first (handy when you want to split a list
in half).
Middle of odd and even lists
first_middle assumes a non-empty list. Splitting
at the first middle gives halves of sizes
ceil(n/2) and floor(n/2).
Cycle detection (Floyd's tortoise and hare). If
some node's next points back into the list, a
plain walk never ends. Run fast & slow instead:
- No cycle:
fasthitsNone. Done,False. - Cycle: both pointers end up circling. Each step
fastgains exactly one node onslow, so the gap between them shrinks by 1 until it's 0: they meet. Compare nodes withis, not values.
Bonus: to find where the cycle starts, put one
pointer back at head after they meet and move
both one step at a time; they meet again at the
cycle's entrance.
Build a cycle and catch it
A hash set of visited nodes also works (O(n) space). Floyd's version needs only two pointers, which is what interviewers are fishing for.
What does this print?
A fixed gap: the nth node from the end. Start
two pointers together, move fast ahead n
steps, then move both until fast hits the end.
slow is now n nodes behind the end.
Start both at a dummy node and stop when
fast.next is None: slow then sits just
before the target, which is exactly where you need
to be to delete it.
Merging. To merge two sorted lists, keep a
tail that starts at a dummy; repeatedly attach the
smaller front node and advance. When one list runs
out, attach the rest of the other in one go.
Split, reverse, merge. Many "rearrange the list"
problems are these three moves in a row: find the
middle (fast & slow), cut the list there
(slow.next = None), reverse the second half, then
weave or compare the halves. Palindrome check and
Reorder List both work this way.
Merging two sorted lists with a tail pointer
No new nodes are created: the merge relinks the
existing ones. a or b picks whichever list still
has nodes (or None if both are empty).
In Floyd's cycle detection, why is fast guaranteed to meet slow once both are inside the cycle?
Does the list loop?
Write has_cycle(head) that returns True if
following next pointers from head ever revisits
a node, and False otherwise (including for an
empty list).
Use fast & slow pointers so you need only O(1) extra space.