Linked List Cycle
Detect a cycle in a linked list — Set of nodes vs Floyd tortoise and hare O(1) space, plus find-entrance follow-up.
- dsa
- linked-list
- interview
- Meta
- Amazon
- Microsoft
The problem
Return true if the linked list has a cycle (some node reachable again by following next).
3 → 2 → 0 → -4
↑ |
└─────────┘
→ true
Brute: hash set
function hasCycleSet(head: ListNode | null): boolean {
const seen = new Set<ListNode>();
let cur = head;
while (cur) {
if (seen.has(cur)) return true;
seen.add(cur);
cur = cur.next;
}
return false;
}
| Time | O(n) |
| Space | O(n) |
Optimal: Floyd’s tortoise and hare
Slow moves 1, fast moves 2. If there’s a cycle they meet. If fast hits null, no cycle.
class ListNode {
val: number;
next: ListNode | null;
constructor(val = 0, next: ListNode | null = null) {
this.val = val;
this.next = next;
}
}
function hasCycle(head: ListNode | null): boolean {
let slow = head;
let fast = head;
while (fast && fast.next) {
slow = slow!.next;
fast = fast.next.next;
if (slow === fast) return true;
}
return false;
}
| Time | O(n) |
| Space | O(1) |
Why they meet
In a cycle of length C, relative speed 1 closes the gap. Standard cycle detection proof — sketch it if asked.
Follow-up: cycle entrance (LC 142)
After meeting, reset one pointer to head; both move 1 until equal → entrance.
function detectCycle(head: ListNode | null): ListNode | null {
let slow = head;
let fast = head;
while (fast && fast.next) {
slow = slow!.next;
fast = fast.next.next;
if (slow === fast) {
slow = head;
while (slow !== fast) {
slow = slow!.next;
fast = fast!.next;
}
return slow;
}
}
return null;
}
Used in Find Duplicate Number as well.
Edge cases
- Empty / single node no self-loop
- Self-loop at head
- Cycle not at head
- Long acyclic list
Common mistakes
- Comparing
valinstead of node identity - Fast moves 2 without null checks
- Modifying list (mark visited) when read-only expected
Interview delivery
- Set approach first.
- Floyd for O(1) space.
- Null-safe fast.
- Optional entrance.
- Complexities.
Mental model
If you can mark nodes, a set is trivial. Without extra memory, two pointers at different speeds collide iff a cycle exists. The meeting point is not necessarily the entrance — that’s a second phase.
Complexity table
| Approach | Time | Space | Mutates? |
|---|---|---|---|
| Hash set | O(n) | O(n) | no |
| Floyd | O(n) | O(1) | no |
| Mark visited bit in val | O(n) | O(1) | yes (bad) |
Out-loud answer
“Detect cycle with slow/fast pointers. Advance while fast and fast.next exist; equal means cycle. O(1) space. Set is the clear O(n) space alternative. Entrance is LC 142.”
Related
- Find Duplicate Number
- Reverse Linked List
- Add Two Numbers Linked List
- Copy List with Random Pointer
- JavaScript Interview Guide