Linked List Cycle II

MediumLinked List · Fast & Slow Pointers🧩 Fast & Slow PointersLeetCode #142 ↗Updated

Problem

You get the head of a singly linked list whose tail may point back to an earlier node, forming a cycle. Return the node where the cycle begins (the first node reached twice when walking from head), or null if the list ends. Do not modify the list.
Input[3,2,0,-4], tail → idx 1Outputnode at index 1 (val 2)
Input[1,2], tail → idx 0Outputnode at index 0 (val 1)
Input[1], no cycleOutputnull

0 ≤ nodes ≤ 104  ·  -105 ≤ Node.val ≤ 105  ·  Follow-up: O(1) extra memory.

Try it yourself

Java
class Solution {
    public ListNode detectCycle(ListNode head) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
When the hare (2 steps) meets the tortoise (1 step) inside the loop, the distance from head to the cycle entry equals the distance from the meeting point to the entry (mod cycle length). So restart one pointer at head and step both by 1.
PatternFast & Slow Pointers

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 ForceRescan the Prefix for Each Node

Time O(n2)Space O(1)

Walk the list counting steps. For the node reached at step s, scan the first s nodes of the walk again; if it is among them, it is the first node visited twice — the cycle entry. Reaching null means no cycle.

Java
public ListNode detectCycle(ListNode head) {
    ListNode cur = head;
    for (int steps = 0; cur != null; steps++, cur = cur.next) {
        ListNode p = head;
        for (int k = 0; k < steps; k++, p = p.next) {
            if (p == cur) return cur; // seen before -> cycle entry
        }
    }
    return null;
}

Constant memory, but quadratic — ~5·107 checks at n = 104.

At a glance

LevelApproachTimeSpace
Brute ForceRescan the Prefix for Each NodeO(n2)O(1)
BetterHash Set of Visited NodesO(n)O(n)
OptimalFloyd's Tortoise & HareO(n)O(1)
Common pitfalls
  • Checking slow == fast before moving — they start equal at head.
  • Loop guard fast.next != null without fast != null — NPE on even-length lists.
  • Comparing vals instead of references — duplicate values are not a cycle.
Interview tips
  • Draw the a / b / L diagram and derive a = kL − b on the whiteboard.
  • Mention the HashSet version first, then optimise memory with Floyd.
  • Argue termination: inside the loop the gap shrinks by 1 each step, so they meet within L steps.
Pattern
Fast & slow pointers → detect a cycle (and its entry) in a linked list or functional graph.
My notes saved in this browser