Linked List Cycle

A fast pointer laps a slow one if and only if there's a loop.

Approach

Advance one pointer by one and another by two each step. If they ever meet, there's a cycle; if the fast pointer reaches the end, there isn't. Floyd's trick detects loops in O(1) space, unlike a visited-set approach.

Time complexity

O(n)

Space complexity

O(1)

Common mistake

Checking pointer identity before advancing, or not guarding fast.next before taking two steps.

Interactive walkthrough — step through it below, free and without an account

Problem

Given the head of a singly linked list, determine whether repeatedly following next eventually revisits a node. Return true when the list loops back to an earlier node; otherwise return false when traversal reaches null.

Examples

Input: head = [3,2,0,-4], pos = 1

Output: true

The last node points back to the node containing 2, so traversal cycles through 2 → 0 → -4.

Input: head = [1,2], pos = -1

Output: false

The second node points to null, so the traversal terminates.

Problem

Problem

Given the head of a singly linked list, determine whether repeatedly following `next` eventually revisits a node. Return `true` when the list loops back to an earlier node; otherwise return `false` when traversal reaches `null`.

Problem and Goal

Learning goal: Recognize when a linked-list traversal contains a loop and why revisiting a node matters.

Core idea A normal singly linked list eventually reaches null. A cyclic list never does: its next pointers repeatedly send traversal through nodes that were already visited. The task is to detect that structural behavior, not merely to find duplicate values, because two different nodes may contain the same value.

Algorithm plan

  • Start two references at the head: slow and fast.
  • Move slow one link at a time.
  • Move fast two links at a time.
  • Report a cycle if the references become identical.
  • Report no cycle if fast or fast.next is null.

Micro-example For 3 → 2 → 0 → -4 → 2, the final arrow returns to the node containing 2. For 1 → 2 → null, every traversal eventually stops.

Pitfalls

  • Compare node identity, not node values.
  • An empty list has no cycle.
  • A single node pointing to itself is still a cycle.

Recap

  • Cycles are about repeated nodes, not repeated values.
  • Termination at null proves that no cycle exists.
  • Floyd's method detects both outcomes with two moving references.

Problem and Goal

Follow links, not values

A cycle exists when a `next` pointer leads back to an existing node. Equal values alone do not imply a cycle.

The algorithm compares references such as `slow === fast`, never just `slow.val === fast.val`.

Key Idea: A Pointer Race

Learning goal: Understand why a fast pointer must meet a slow pointer exactly when a loop exists.

Core idea Imagine the list as a straight path leading into a circular track. Before entering the track, both pointers move forward. Once both are on the circular portion, fast gains one node per round on slow, so it eventually laps and meets it. If there is no circular portion, fast simply reaches the end first.

Key insight

Inside a loop, the distance between the pointers changes by one position modulo the loop length. Repeatedly subtracting one eventually produces zero.

Data structure model

  • slow advances by slow = slow.next.
  • fast advances by fast = fast.next.next.
  • The test is made after both have advanced.
  • Before taking two steps, verify fast !== null and fast.next !== null.

Micro-example In 3 → 2 → 0 → -4 → 2, after a few rounds the pointers occupy the same -4 node. In 1 → 2 → null, fast.next is eventually null, so the loop stops safely.

Pitfalls

  • Checking pointer identity before the first movement can misclassify slow === fast at the head.
  • Moving fast twice without guarding fast.next can dereference null.
  • The speed difference is one node per iteration, which is what guarantees a meeting.

Recap

  • A loop turns the suffix into a circular track.
  • fast laps slow if and only if that track exists.
  • The null guard protects the two-step movement.

Key Idea: A Pointer Race

Once both pointers enter the cycle, positions repeat modulo the cycle length.

A one-node speed advantage eventually closes any gap.

Main Approach and Correctness

Learning goal: Translate the pointer race into a safe, implementation-ready algorithm.

Core idea Initialize both references at the head, then perform a guarded movement loop. The guard is evaluated before fast.next.next, because fast may already be null or may point to the final node. After each complete movement, pointer identity is checked. A meeting is conclusive evidence of a cycle because two traversals starting at the same head can only occupy the same node after different progress if the structure loops.

Algorithm plan

Code
slow = head
fast = head
while fast is not null and fast.next is not null:
    slow = slow.next
    fast = fast.next.next
    if slow is fast:
        return true
return false

Why it works

The only way the faster reference can catch the slower one is for the path ahead to wrap around. A finite acyclic path has no place to wrap.

Micro-example For the cycle 3 → 2 → 0 → -4 → 2, both pointers enter the loop and eventually coincide.

Pitfalls

  • The loop guard belongs before the two-step assignment.
  • Use reference identity, such as slow === fast.
  • Do not allocate a set of visited nodes if constant space is required.

Recap

  • Guard, advance both, then compare.
  • A meeting proves a loop; a null guard proves termination.
  • The method uses constant auxiliary space.

Main Approach and Correctness

ApproachTimeExtra spaceCore trade-off
Fast & slow pointersO(n)O(1)Uses a speed difference to detect a meeting
Visited setO(n)O(n)Stores every node identity encountered

Walkthrough: One Complete Cycle

Learning goal: Trace every pointer movement on the example 3 → 2 → 0 → -4 → 2.

Core idea The tail does not point to a new node; it points back to the node containing 2. We will label nodes by identity so the repeated destination is visible. Both pointers begin at the head, but we do not declare a cycle merely because they initially share that node. Instead, each round advances slow once and fast twice, then checks whether they meet.

Data structure model

  • n1 stores 3 and points to n2.
  • n2 stores 2 and points to n3.
  • n3 stores 0 and points to n4.
  • n4 stores -4 and points back to n2.
  • The cycle is n2 → n3 → n4 → n2.

Micro-example Round 1: slow reaches n2; fast reaches n3. Round 2: slow reaches n3; fast reaches n2. Round 3: both reach n4, so the references are identical.

Pitfalls

  • n2 appears again as a destination, but it is one stable node, not a copied value.
  • fast must take two valid links at every round.
  • The meeting can happen anywhere inside the loop, not necessarily at its entry.

Recap

  • The visualization tracks node IDs and pointer positions.
  • The pointers meet at n4 after advancing.
  • That meeting returns true.

Walkthrough: One Complete Cycle

Animate Floyd's algorithm on the example 3 → 2 → 0 → -4 → 2, where the tail links back to the node containing 2.

Linked list
1 / 9
Start together at node 3; compare only after advancing.
head →3
currslowfast
3
 
2
 
0
 
-4
next 2

Action: init

The tail arrow visibly returns to node 2.Every pointer is on a valid node before movement.
1 / 9

Pitfalls and Edge Cases

Learning goal: Prevent the two implementation mistakes that most often break cycle detection.

Core idea The safest loop structure checks whether two steps are available before moving fast. It then advances both pointers and compares their identities. This ordering handles empty lists, one-node lists, and ordinary terminating lists without special-case code.

Algorithm plan

  • Empty list: head is null, so the loop never starts and the answer is false.
  • One node to null: fast.next is null, so the answer is false.
  • One node to itself: both pointers move back to that same node, so the answer is true.
  • Any longer cycle: continue until the references meet.

Common pitfall

Checking slow === fast before advancing is wrong when both start at head; every nonempty list would appear cyclic immediately.

Null guard

Never evaluate fast.next.next unless both fast and fast.next are non-null.

Micro-example For 1 → 2 → null, the initial guard fails because fast.next eventually becomes null. For 7 → 7, the self-link makes the pointers meet after a movement.

Pitfalls

  • Do not compare val fields.
  • Do not forget that head = null is valid.
  • Do not use a visited set when the target space is O(1).

Recap

  • Guard before the two-step move.
  • Compare after advancing.
  • Identity, not value equality, determines a meeting.

Pitfalls and Edge Cases

Which loop is safe and correctly ordered for Floyd's cycle check?

Complexity and Wrap-up

Learning goal: Explain why Floyd's method meets the target complexity and summarize the reusable pattern.

Core idea The pointers may traverse a short non-cyclic prefix and then move around a cycle. Each movement advances through an existing node, and the fast pointer either reaches null or catches the slow pointer after a linear number of steps. The algorithm stores only two references, so its auxiliary memory does not grow with the list size.

Algorithm plan

  • Maintain slow and fast only.
  • Spend constant work per loop iteration.
  • Stop on either a guarded null condition or pointer identity equality.
  • Return the corresponding Boolean result.

Micro-example The walkthrough visits a constant number of pointer states for its four-node structure. For a list with n nodes, the same process scales linearly rather than storing all n identities.

Pitfalls

  • A visited-set solution is correct but uses O(n) extra space.
  • Big-O counts nodes and pointer operations, not the numeric values stored in nodes.
  • The method detects existence; finding the cycle entry requires a second Floyd phase.

Recap

  • Time complexity: O(n).
  • Auxiliary space: O(1).
  • Fast laps slow if and only if a loop is reachable.
  • The reusable pattern is a speed difference plus a guarded identity check.

Complexity and Wrap-up

Summarize the cost of Floyd's cycle detection and contrast its space usage with a visited set.

Complexity analysis
Time
O(n)
Space
O(1)
Where the time goes
  • Advance slow and fastEach iteration performs a constant number of pointer reads.dominantO(n)
  • Compare referencesIdentity comparison is constant time.O(1)
  • Store pointer stateOnly slow and fast are retained.O(1)
How it grows
input size n →opsO(n²)O(n log n)O(n)O(log n)O(1)
Roughly what that costs
n101001,00010,000
O(n)101001K10K

Floyd's method is optimal for this target: linear traversal with constant auxiliary space.

Now try it on your own problem

Paste any LeetCode problem — or one of your own — and codebrew builds a walkthrough like this one for it.

Build a lesson from any problem

Related problems