Linked List Cycle
Problem
head of a singly linked list. Some node's
next pointer may lead back to an earlier node, so following links would
go round forever. Return true if such a loop exists, otherwise
false. (The test harness describes the loop with pos, the index
the tail connects to, or -1 for none — you never receive it.)head = [3,2,0,-4], pos = 1Outputtrue (tail -4 links back to 2)head = [1,2], pos = 0Outputtruehead = [1], pos = -1Outputfalse0 ≤ n ≤ 104 · -105 ≤ Node.val ≤ 105 · Follow-up: use O(1) extra memory.
Try it yourself
class Solution {
public boolean hasCycle(ListNode head) {
}
}
Instinct A next-step function you can follow (list nodes, digit-square sums, array-as-pointers) and you need a cycle, its entry, or the middle in O(1) space.
Memory hack Tortoise and hare - on a loop track the hare laps the tortoise; restart the tortoise at the gate and they meet at the loop's door.
Open the Fast & Slow Pointers guide →Approaches
Brute ForceRemember Visited Nodes (HashSet)
O(n)Space O(n)Walk the list and store each node reference (not its value — values
can repeat). If we ever reach a node already in the set, the walk has looped.
Reaching null means the list ends, so there is no cycle.
public boolean hasCycle(ListNode head) { Set<ListNode> visited = new HashSet<>(); for (ListNode cur = head; cur != null; cur = cur.next) { if (!visited.add(cur)) return true; // seen this exact node before } return false; }
Linear and simple, but stores up to n references — fails the follow-up.
OptimalFloyd’s Tortoise & Hare
O(n)Space O(1)slow advances one node, fast two. Without a cycle,
fast hits null first. With one, once both are inside the
loop the gap between them shrinks by exactly 1 per step, so they meet within one
lap — at most O(n) steps in total.
public 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; // hare caught the tortoise } return false; }
Dry run[3,2,0,-4], pos = 1
- start3s f20-4both at head
- step 132s0f-4s=2, f=0
- step 232f0s-4f: -4 → 2 (loop)
- step 3320-4s fmeet ⇒ true ✔
Constant memory, single pass — the classic answer.
head and step both
by one — they meet again at the cycle's entry (LC 142).At a glance
| Level | Approach | Time | Space |
|---|---|---|---|
| Brute Force | Remember Visited Nodes (HashSet) | O(n) | O(n) |
| Optimal | Floyd’s Tortoise & Hare | O(n) | O(1) |
- Checking only
fast != null—fast.next.nextthen throws NPE. - Comparing node values instead of references — duplicate values give false positives.
- Testing
slow == fastbefore moving — they start equal, so it always says true.
- Mention the HashSet idea in one line, then go straight to Floyd for O(1) space.
- Explain why they must meet: the gap closes by one each step inside the loop.
- Check aloud: empty list, single node without loop, single node pointing to itself.