How to recognise
a linked list, or any "go to the next" rule, and a question about a cycle, where it starts, or the middle, often with O(1) extra memory.
How to solve problems like this
- Start both pointers at the head.
- Each step, move slow by one and fast by two. Check first that fast and fast.next exist.
- If fast reaches the end, there is no cycle. At that moment slow is at the middle.
- If they meet, there is a cycle. To find where it starts, move one pointer back to the head and step both by one until they meet again.
Variant: Middle
The same, but to find the middle: the fast pointer moves twice as fast, so when it reaches the end, the slow one is exactly halfway. The length need not be known.
- Start both pointers at the head.
- Loop while fast and fast.next both exist: move slow by one and fast by two.
- When the loop stops, slow is the middle. With an odd length fast stops on the last node; with an even length it steps off to none, and slow is on the second of the two middle nodes.
- The same trick splits a list in half: to check a palindrome list, reverse the half after the middle and compare; to sort a list, sort both halves and merge them.
Variant: n apart
The same, but both pointers move at one speed and the fast one starts n nodes ahead. When it reaches the end, the other is n nodes from the end, without counting the length.
- Spot it: a position counted from the end of a linked list, in one pass or without knowing the length.
- Put a dummy node in front of the head and start both pointers on it.
- Move fast n steps alone. Then move both by one until fast.next is none.
- slow is now right before the n-th node from the end: set slow.next = slow.next.next and return dummy.next.
- Rotate a list by k the same way: find the k-th node from the end, cut the list before it, and attach the old tail to the old head. Take k modulo the length first.
Where it's used
- Factoring numbers. Pollard's rho method builds a sequence of numbers that sooner or later loops, and finds the loop with a slow and a fast pointer, without storing the numbers. SymPy has it, for example.
- Cryptography. Pollard also adapted the rho method to discrete logarithms, and it is the best known general attack on elliptic-curve cryptography. 256-bit keys are chosen so that this attack runs out of time.