Linked list slow hops 1, fast (red) hops 2 · the yellow arrow is the tail pointing back
public boolean hasCycle(ListNode head) { ListNode slow = head, fast = head; while (fast != null && fast.next != null) { slow = slow.next; // 1 hop fast = fast.next.next; // 2 hops if (slow == fast) { return true; } } return false;}
- slow
- —
- fast
- —
- rounds
- 0
- gap
- —
Why it works
- Hash set version: remember every node visited and stop on a repeat. O(n) time but O(n) space.
- No cycle: fast runs off the end first, after about n/2 rounds, and the loop condition
fast != null && fast.next != nullstops it safely. - Cycle: both pointers end up going round it. Each round fast moves 2 and slow moves 1, so the gap between them shrinks by exactly 1. It cannot jump over 0, so they must meet within one lap of the cycle.
- Compare nodes, not values:
slow == fastcompares references, which is what you want. Two different nodes can hold the same value, so comparingvalwould be wrong. - O(n) time, O(1) space: two pointers, no extra memory.
- Follow-up (LeetCode 142): to find where the cycle starts, reset one pointer to head after they meet and move both 1 hop at a time. They meet again exactly at the cycle's entry node.