Interview Q&A / Data Structures & Algorithms

IntermediateIn-depthCoding4 min readUpdated 2 Oct 2026

How do you detect a cycle in a linked list?

SHORT ANSWER

Use Floyd's tortoise and hare method. Move a slow pointer one step and a fast pointer two steps at a time. If the fast pointer reaches null, there is no cycle. If the two pointers ever meet, there is a cycle. It runs in O(n) time with O(1) extra space.

Explain it simply

Two friends go for a run. One jogs, the other runs twice as fast. If the track is a straight road, the fast runner simply reaches the end first and they never meet again. If the track is a circular ground, the fast runner will eventually come round from behind and catch up with the jogger.

A linked list with a cycle is the circular ground: some node's next points back to an earlier node, so walking the list never ends. Floyd's method sends a slow pointer and a fast pointer and checks whether they meet.

Line by line

js
function hasCycle(head) {
  let slow = head;
  let fast = head;

  // fast moves two steps, so check both fast and fast.next
  while (fast !== null && fast.next !== null) {
    slow = slow.next; // one step
    fast = fast.next.next; // two steps
    if (slow === fast) {
      return true; // they met inside a loop
    }
  }
  return false; // fast fell off the end, so the list ends
}

// Build 1 -> 2 -> 3 -> 4 -> 5
function build(values) {
  const nodes = values.map((val) => ({ val, next: null }));
  for (let i = 0; i < nodes.length - 1; i++) nodes[i].next = nodes[i + 1];
  return nodes;
}

const straight = build([1, 2, 3, 4, 5]);
console.log(hasCycle(straight[0])); // Output: false

const looped = build([1, 2, 3, 4, 5]);
looped[4].next = looped[1]; // 5 points back to 2
console.log(hasCycle(looped[0])); // Output: true

const selfLoop = build([7]);
selfLoop[0].next = selfLoop[0]; // a single node pointing to itself
console.log(hasCycle(selfLoop[0])); // Output: true

console.log(hasCycle(null)); // Output: false

Trace for the looped list 1 → 2 → 3 → 4 → 5 → back to 2:

Stepslowfast
start11
123
235
343
455 → meet

How it works

Why do they always meet if there is a cycle? Once both pointers are inside the loop, think of the gap from fast to slow going around the loop. Each step, slow moves 1 and fast moves 2, so fast closes the gap by exactly 1. A gap that shrinks by 1 each step must hit 0; it cannot jump over it. So they meet within one lap of the loop.

Why does it stop if there is no cycle? The fast pointer reaches the end in about n/2 steps, and the loop condition checks for null before every jump.

A simpler alternative is to store every visited node in a Set and report a cycle when you see a node twice. It is easy to explain but uses O(n) extra memory, so interviewers usually ask for Floyd's method next.

Complexity

ApproachTimeExtra space
Hash set of visited nodesO(n)O(n)
Floyd's slow and fast pointersO(n)O(1)

Common mistakes

  • Checking only fast !== null and then calling fast.next.next, which crashes when fast.next is null.
  • Comparing node values (slow.val === fast.val) instead of the nodes themselves. Different nodes can hold the same value.
  • Checking slow === fast before moving them. They start at the same node, so the function would wrongly return true at once.
  • Forgetting the empty list and single-node cases.

What to say in the interview

"I would use Floyd's cycle detection. I keep a slow pointer moving one node at a time and a fast pointer moving two. If there is no cycle, fast reaches null and I return false. If there is a cycle, both pointers end up in the loop, and since fast gains one node per step on slow, they must meet, so I return true. It is O(n) time and O(1) space. A hash set of visited nodes also works but uses O(n) space."

Follow-up questions

  • How do you find the node where the cycle begins?
  • How do you find the length of the cycle?
  • How can the same idea find a duplicate number in an array of n + 1 integers from 1 to n?
  • How would you find the middle of a linked list in one pass?

Go deeper

Read these once the basics above feel easy.

Finding where the cycle starts: after slow and fast meet, move one pointer back to the head. Now move both pointers one step at a time. The node where they meet again is the start of the cycle.

js
function cycleStart(head) {
  let slow = head, 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;
}

const a = { val: 1, next: null }, b = { val: 2, next: null }, c = { val: 3, next: null };
a.next = b; b.next = c; c.next = b; // 1 -> 2 -> 3 -> back to 2
console.log(cycleStart(a).val); // Output: 2

Cycle length: once they meet, keep one pointer still and walk the other around the loop, counting steps until it comes back.

#linked-list#two-pointers#floyd-cycle-detection

Related questions

Practise more Data Structures & Algorithms questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open Data Structures & Algorithms quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.