Floyd's Cycle Detection (Tortoise and Hare)
Detects cycles in a linked list (or any sequence defined by a next-state function) using two pointers moving at different speeds; also finds the cycle start and length.
Syntax
floydCycle(head) Parameters
| Name | Type | Required | Description |
|---|---|---|---|
head | ListNode | null | Yes | Head of a singly-linked list. Each node has a `val` and `next` pointer. |
Returns
boolean — True if a cycle exists, false otherwise.
Examples
class ListNode { constructor(val) { this.val = val; this.next = null; } }
function hasCycle(head) {
let slow = head, fast = head;
while (fast !== null && fast.next !== null) {
slow = slow.next;
fast = fast.next.next;
if (slow === fast) return true;
}
return false;
}
// Build: 1→2→3→4→2 (cycle at node 2)
const n1=new ListNode(1),n2=new ListNode(2),n3=new ListNode(3),n4=new ListNode(4);
n1.next=n2; n2.next=n3; n3.next=n4; n4.next=n2; // cycle
console.log(hasCycle(n1));
const m1=new ListNode(1),m2=new ListNode(2);
m1.next=m2;
console.log(hasCycle(m1));
Output
true
false
// Find the START of the cycle
class ListNode { constructor(val) { this.val = val; this.next = null; } }
function detectCycleStart(head) {
let slow = head, fast = head;
while (fast && fast.next) {
slow = slow.next; fast = fast.next.next;
if (slow === fast) {
// Reset one pointer to head; advance both one step at a time
slow = head;
while (slow !== fast) { slow = slow.next; fast = fast.next; }
return slow; // cycle start node
}
}
return null;
}
const a=new ListNode(3),b=new ListNode(2),c=new ListNode(0),d=new ListNode(-4);
a.next=b; b.next=c; c.next=d; d.next=b; // cycle starts at b
console.log(detectCycleStart(a)?.val);
Output
2
Notes
| Case | Time | Space |
|---------|------|-------|
| Best | O(n) | O(1) |
| Average | O(n) | O(1) |
| Worst | O(n) | O(1) |
**Why it works**: if a cycle of length λ exists starting at distance μ
from the head, the slow and fast pointers will meet inside the cycle.
After the meeting point, resetting one pointer to head and advancing
both one step at a time will cause them to meet exactly at the cycle
start (distance μ from the head). The algorithm applies to any function
ƒ where the sequence x, ƒ(x), ƒ(ƒ(x)), … is eventually periodic —
useful for finding repeated states in pseudorandom number generators.