2Brute2Best
🔥0

Linked List Cycle

Easy·LeetCode #141Basic Anchor
LeetCode
30-Second Mental ModelFast & Slow pointers — cycle detection (Floyd)
Complexity:O(N)→O(N)
Key Insight

Start two pointers at head. Each move, slow goes 1 step and fast goes 2 steps. If the list ends, fast reaches null first and we return false. If there is a loop, both pointers end up going round it, and fast gets 1 node closer to slow every move, so it must land exactly on slow. Then we return true.

Core Validity Invariant

There is a cycle exactly when slow and fast land on the same node; if fast or fast->next becomes null, the list has an end.

01

Problem

You are given head, the first node of a singly linked list.

The list has a cycle if you can keep following next pointers forever, because some node's next points back to a node that came earlier. Return true if the list has a cycle, and false if following next eventually reaches null.

pos in the examples is only used to build the test list: it is the index of the node the tail links back to (-1 means no cycle). Your function does not receive it.

Input

head — the first node of the list (it can be null).

Output

true if the list contains a cycle, otherwise false.

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

The tail (-4) links back to the node at index 1 (value 2), so 2 → 0 → -4 → 2 → … repeats forever.

Example 2
Input: head = [1, 2], pos = 0
Output: true

The tail (2) links back to the head (1).

Example 3
Input: head = [1], pos = -1
Output: false

One node whose next is null. The walk ends, so there is no cycle.

Constraints
  • • The number of nodes is in the range [0, 10^4]
  • • −10^5 ≤ Node.val ≤ 10^5
  • • pos is −1 or a valid index in the list
  • • Follow-up: can you solve it using O(1) extra memory?
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    If there is no cycle, what does the walk along next eventually reach?

  2. 2.

    If there is a cycle, what happens to that walk instead?

  3. 3.

    To notice a repeat, what exactly should I remember about each node — its value, or the node itself?

  4. 4.

    Could two different nodes hold the same value? What would that do to a check based on values?

  5. 5.

    Without any memory, how could two walkers tell me they are going round in a circle?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceHash set of node pointers; seeing a node twice means a cycleO(N)O(N)
Optimalslow moves 1, fast moves 2; they meet only if there is a cycleO(N)O(1)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “determine if the list has a cycle”We only need yes/no, not where the loop is → two pointers can answer it.
  • “linked list, follow next”Each node has exactly one next, so the walk is a path that either ends or bends into one loop (a "ρ" shape).
  • “O(1) memory follow-up”No visited set → let a fast and a slow pointer find the repeat for us.
one next per node+does the walk repeat?+O(1) memory→Fast & Slow pointers — cycle detection (Floyd)

This is the anchor of the cycle sub-pattern: the plainest form of Floyd, where we only check whether they meet. The later questions reuse the same meeting: Happy Number runs it on numbers instead of nodes, Find Length of Loop walks once round from the meeting node, and Linked List Cycle II adds a second phase to find where the loop starts.

10

Don't make this mistake

Remembering values instead of nodes
✗ unordered_set<int> seen; if (seen.count(cur->val)) return true; seen.insert(cur->val);
✓ unordered_set<ListNode*> seen; if (seen.count(cur)) return true; seen.insert(cur);

Different nodes can hold the same value. On [7, 7, 7] with no cycle, a value set sees 7 twice and wrongly says "cycle". A cycle means the same node comes back, so store the pointer.

Checking fast->next without checking fast
✗ while (fast->next != nullptr && fast->next->next != nullptr)
✓ while (fast != nullptr && fast->next != nullptr)

For an empty list head is null, so fast->next crashes straight away. Always check fast before you read fast->next. The order matters: && stops at the first false part.

Checking slow == fast before moving
✗ while (fast && fast->next) { if (slow == fast) return true; slow = slow->next; fast = fast->next->next; }

Both start at head, so they are equal before the first move and this returns true for every list with 2+ nodes. Move first, then compare.

Treating it as "just walk until null"
✗ while (cur) cur = cur->next; return false;

This is the pattern-confusion trap: a normal list walk assumes the list ends. With a cycle it never reaches null and loops forever. Whenever a walk might repeat, you need either a visited set or a second, faster pointer to detect it.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Linked List — Fast & Slow translate into production architectures and low-level memory mechanics.