Linked List Cycle
Detect whether a list loops back on itself, in O(1) space. Move slow one step and fast two steps. If there's a cycle, fast laps slow and they meet; otherwise fast reaches null.
Traced input: head = [3, 2, 0, -4], tail links to index 1 → true. Original problem: neetcode.io/problems/linked-list-cycle-detection
Complexity
BestO(1)
AverageO(n)
WorstO(n)
SpaceO(1)
Once both are in the cycle, the gap closes by one each step.
Key idea
- In a cycle, the faster runner must eventually catch the slower one.
- Each step, the distance between them shrinks by exactly one, so fast can't jump over slow.
- Check
fast != null && fast.next != nullbefore moving fast.
Common mistakes
- A HashSet of visited nodes works but uses O(n) space.
- Checking
slow == fastbefore the first move (they start equal). - Forgetting
fast.next != nulland crashing on even-length lists.
Solution
Java
boolean hasCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}Python
def hasCycle(head: Optional[ListNode]) -> bool:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow is fast:
return True
return FalseC++
bool hasCycle(ListNode* head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
return true;
}
}
return false;
}Edge cases
Each one has its own trace in the interactive view.
| Case | Input | Answer |
|---|---|---|
| No cycle fast reaches null. | head = [1, 2, 3] | false |
| Empty list No nodes at all. | head = [] | false |
| Single node pointing to itself fast and slow meet on the only node. | head = [1], tail links to index 0 | true |
Single node, no cyclefast.next is null immediately. | head = [1] | false |