Hi👋SpeedAlgo • Deliberate Practice & Cognitive Ergonomics for Software Engineers

An interactive algorithm mastery and technical interview preparation platform published by Hi👋WebEnterprise. Built for senior and staff software engineers preparing for rigorous coding screens at top tech companies (FAANG/MAMAA).

13 Core Algorithmic Patterns & 225 Practice Problems

  • 1. Two Pointers (16 Paradigms, 43 Problems): Opposite ends, sorted pair sums, palindrome verification, trapping rain water, 3Sum, container with most water — includes the Sliding Window and Fast & Slow Pointers paradigms (contiguous subarray invariants, longest substrings, Floyd's cycle detection, linked list middle).
  • 2. Binary Search (9 Paradigms, 14 Problems): Monotonic predicate partitioning (feasible(x)), boundary search, rotated sorted arrays, square roots, minimum ship capacity, median of two sorted arrays, matrix median on value range.
  • 3. Bit Manipulation (5 Paradigms, 11 Problems): Counting set bits, XOR cancellation, bit reversal, bitmask pairing, maximum XOR with a bitwise trie.
  • 4. Math & Geometry (8 Paradigms, 14 Problems): Sieve of Eratosthenes, integer/roman conversions, modular arithmetic, geometric simulation.
  • 5. Tree/Graph Depth-First Search (15 Paradigms, 24 Problems): Path sums, lowest common ancestor, tree diameter, validating BSTs, tree DP (House Robber III, Binary Tree Cameras).
  • 6. Tree/Graph Breadth-First Search (5 Paradigms, 12 Problems): Level-order traversals, shortest path in unweighted graphs, zig-zag traversals, rotting oranges, word ladders.
  • 7. Graphs (12 Paradigms, 22 Problems): Topological sort, cycle detection, Dijkstra's algorithm, bipartite graph validation, network delay.
  • 8. Backtracking (6 Paradigms, 14 Problems): Subsets, permutations, combinations, constraint satisfaction, pruning, N-Queens, Sudoku solver.
  • 9. Dynamic Programming (13 Paradigms, 28 Problems): Memoization vs tabulation, 0/1 knapsack, unbounded knapsack, coin change, edit distance, longest common subsequence.
  • 10. Heap / Priority Queue (9 Paradigms, 11 Problems): Running medians, top-k elements, interval scheduling, IPO, k-way merges.
  • 11. Advanced Data Structures (7 Paradigms, 17 Problems): Trie (prefix tree), Union-Find (Disjoint Set Union), LRU Cache, LFU Cache, range-sum queries with updates.
  • 12. Stack (5 Paradigms, 9 Problems): Next greater element, largest rectangle in histogram, remove k digits, decode string, min stack.
  • 13. Intervals & Greedy (2 Paradigms, 6 Problems): Merge intervals, interval scheduling, meeting rooms by sweep line, jump game.

4-Stage Deliberate Practice Framework

  1. Stage 1 (Compare & Learn): Read the pattern's mental model, loop invariant and Big-O proof, compare the pattern's template with the problem's solution side by side, and use the step-by-step debugger. The solution can also be shown in C#, Java, TypeScript, C++, Go or Rust for almost every problem.
  2. Stage 2 (Active Recall): Rebuild the solution from memory in a code editor, with an invariant checklist and optional progressive hints, and check it against a judged test suite.
  3. Stage 3 (AI Interview Coach, coming soon): A mock-interview stage still in development; for now, students go straight from Stage 2 to Stage 4.
  4. Stage 4 (Solve on Your Own): Solve a new problem on your own against a 15-minute timer; your code is graded against a test suite. Python and TypeScript run in your browser and C# runs on our server (design problems grade in Python and TypeScript).

Equipped with a spaced-repetition review hub on a fixed 7-step schedule (1 day up to 90 days), a two-pane Studio workspace, and study notes.

Pricing, Access & Commercial Terms

  • Core Curriculum: 100% Free. No credit card required.
  • Coins: New accounts get 40 free coins once, the daily claim adds +20 coins once a day, and inviting a friend earns you +25 coins when they complete their first practice step. These are the only ways to earn coins.
  • AI Coach: Each AI coach question costs 1-5 coins, priced by the server according to its size.
  • BYOK (Bring Your Own Key): AI coaching is free with your own Google Gemini, OpenAI or OpenRouter API key (BYOK).
  • Extras: Coins also unlock extras for 24 hours: a Recall hint level (1 coin), a Solve solution reveal (2), a LeetCode problem card's solutions (1) and a pattern's extra canonical problems (1).
  • Payments & Refunds: Nothing on the site is sold for money: coins can only be earned, never bought. There are no subscriptions or charges, so there is nothing to refund.
  • Platform Operator: Hi👋WebEnterprise. Support & policies at hispeedalgo.com.
Skip to main content
Hi👋SpeedAlgo

Invariant-First Algorithmic Mastery

Arena
238Items
Theory Context•Two Pointers & Sliding Window
MediumLC 142

Linked List Cycle II (LeetCode 142)

Target Frequency:AmazonMicrosoftGoogle

You're given the head of a linked list that may loop back on itself. Find and return the exact node where that loop begins — or null if the list has no loop at all.

(A test harness may describe the loop internally with a 0-indexed pos marking where the tail's next pointer reconnects, using -1 for no loop, but that index is never handed to your function.)

You must leave the linked list unmodified.

Worked Examples

Example 1
Input:head = [3,2,0,-4], pos = 1
Output:tail connects to node index 1
Cyclic Linked List TopologyCycle at Node[1]
Floyd Cycle Detection
Access Road (L):1 node
Cycle Loop (C):3 nodes
Loop Entry:Node[1] (val: 2)
Collision / Meeting Point Detected!
3[0] head🐢 slow🐇 fast2[1] 0[2] -4[3] tailnext = Node[1]
Fast / Slow Pointer Invariant

Slow advances 1 step (slow = slow.next) while Fast advances 2 steps (fast = fast.next.next). The distance between them decreases by 1 on every cycle iteration.

Cycle Origin Recovery ($L = kC - M$)

Upon collision inside the loop, moving one pointer back to the list head and advancing both at 1 step guarantees they will collide at the exact cycle entrance node.

320-4
Explanation: The tail node (-4) loops back into the node at index 1 (value 2), so that node is the cycle's entry point.
Example 2
Input:head = [1,2], pos = 0
Output:tail connects to node index 0
12
Explanation: The tail node (2) loops back into the node at index 0 (value 1), so that node is the cycle's entry point.
Example 3
Input:head = [1], pos = -1
Output:no cycle
1
Explanation: There is no cycle in the linked list.

⚖️Formal Constraints & Bounds

  • The number of the nodes in the list is in the range [0, 104].

  • -105 <= Node.val <= 105

  • pos is -1 or a valid index in the linked-list.

Deep-Dive & Conceptual Insights

Core Insight

The distance from the head to the cycle origin equals the distance from the Phase 1 collision point to the cycle origin (L = k·C - x).

Real-World Scenario & Production Applications

Detecting circular dependencies in build systems, finding recurring loop states in state machines, and reference-counted garbage collection.

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Phase 1 -- Fast & Slow Pointer Collision

Advance slow at 1x speed and fast at 2x speed until they collide inside the cycle loop, proving a cycle exists. If fast reaches null, terminate early.

Mathematical Recurrence / Code Invariant
slow, fast = head, head
while fast and fast.next:
    slow = slow.next; fast = fast.next.next
    if slow == fast: break
else: return None

Step-by-Step Execution Trace Table

PhaseStepPtr 1 PositionPtr 2 PositionDistance / ActionStatus
Phase 1: Rendezvous1-3slow at Node(-4)fast at Node(-4)Standard Floyd cycle detectionRendezvous confirmed at Node(-4)
Phase 2: Origin SeekInitp1 = head (Node 3)p2 = meeting (Node -4)Reset one pointer to head; keep other at meeting nodeBoth step at uniform speed 1
Phase 2: Origin Seek1p1 = p1.next (Node 2)p2 = p2.next (Node 2)Step 1: 3 -> 2; -4 -> 2p1 == p2! Cycle entry is Node(2)
Worked on Paper

The Math, Step by Step

1. The distances in the list

Count distances in steps, where one step follows one next pointer. Name three numbers:

  • aaa is the number of steps from head to the entrance, the first node of the cycle. This is the node the code must return.
  • LLL is the cycle length, the number of nodes in the cycle. Walking LLL steps inside the cycle brings you back to the same node.
  • bbb is the number of steps from the entrance forward to the node where slow and fast meet, with 0≤b<L0 \le b < L0≤b<L.
320-4

The picture shows Example 1. The tail node −4-4−4 points back to the node with value 2 at index 1. So the entrance is index 1, a=1a = 1a=1, and the cycle holds the three nodes 2, 0 and −4-4−4, so L=3L = 3L=3.

2. Where the two pointers are after sss rounds

Both pointers start at head. In every round of phase 1, slow moves 1 step and fast moves 2 steps. After sss rounds, slow has moved sss steps and fast has moved 2s2s2s steps.

The number of steps a pointer has moved decides where it stands. A pointer that moved fewer than aaa steps is still before the cycle. A pointer that moved t≥at \ge at≥a steps is inside the cycle, (t−a) mod L(t - a) \bmod L(t−a)modL steps past the entrance. Here x mod Lx \bmod LxmodL is the remainder after dividing xxx by LLL.

3. Why phase 2 stops at the entrance

Suppose the pointers meet after sss rounds. They stand on the same node inside the cycle. fast has moved sss steps more than slow. Two positions in the cycle are the same only when the difference in steps is a whole number of laps. So

s=k⋅Lfor some whole number k≥1s = k \cdot L \quad \text{for some whole number } k \ge 1s=k⋅Lfor some whole number k≥1

slow stands bbb steps past the entrance, so s−as - as−a and bbb differ by whole laps: s−a=b+j⋅Ls - a = b + j \cdot Ls−a=b+j⋅L for some whole number j≥0j \ge 0j≥0. Put s=k⋅Ls = k \cdot Ls=k⋅L into this equation:

a+b=(k−j)⋅La + b = (k - j) \cdot La+b=(k−j)⋅L

So a+ba + ba+b is a whole number of laps. This is the key fact: walking aaa steps forward from the meeting point ends at the entrance. The meeting point is bbb steps past the entrance. Walking aaa more steps puts a pointer a+ba + ba+b steps past the entrance, which is a whole number of laps, so it is at the entrance again.

Phase 2 uses this fact. ptr1 starts at head, and ptr2 starts at the meeting point. Both move one step per round. After aaa rounds, ptr1 reaches the entrance, because the entrance is aaa steps from head. ptr2 also reaches the entrance, by the key fact. They cannot meet earlier. Before round aaa, ptr1 is still outside the cycle, and ptr2 is always inside it.

4. Why phase 1 always ends, and the start at head

If the list has no cycle, fast reaches the end first. The loop while fast and fast.next stops, and the code returns None.

If the list has a cycle, slow enters it after aaa rounds. fast is already inside. From then on, fast gains one step on slow in every round. The gap between them inside the cycle shrinks by one step per round, so it reaches 000 within LLL rounds. So phase 1 ends after at most a+La + La+L rounds.

Both pointers must start at the same node, head. The proof in part 3 uses "fast has moved exactly twice as many steps as slow". If fast started at head.next, that rule would be off by one step. On Example 1 the two pointers of phase 2 would then never stand on the same node, so the loop while ptr1 != ptr2 would never end.

5. Example 1 by hand

head = [3,2,0,-4], pos = 1, so a=1a = 1a=1 and L=3L = 3L=3. Nodes are named by index.

Roundslow movedslow atfast movedfast at
11index 1 (value 2)2index 2 (value 0)
22index 2 (value 0)4index 1 (value 2)
33index 3 (value −4-4−4)6index 3 (value −4-4−4)

The pointers meet after s=3s = 3s=3 rounds, which is 1⋅L1 \cdot L1⋅L. The meeting node, index 3, is b=2b = 2b=2 steps past the entrance. So a+b=1+2=3=La + b = 1 + 2 = 3 = La+b=1+2=3=L, a whole lap. In phase 2, ptr1 moves from index 0 to index 1, and ptr2 moves from index 3 to index 1. They meet after a=1a = 1a=1 round, at index 1. That is the expected output: the tail connects to node index 1.

6. Example 2 by hand

head = [1,2], pos = 0, so a=0a = 0a=0 and L=2L = 2L=2. After round 1, slow is at index 1 and fast is at index 0. After round 2, both are at index 0, so s=2=1⋅Ls = 2 = 1 \cdot Ls=2=1⋅L and b=0b = 0b=0. In phase 2, ptr1 starts at head, index 0, and ptr2 starts at the meeting point, also index 0. The loop while ptr1 != ptr2 runs zero rounds, and the code returns index 0, the expected output. This matches a=0a = 0a=0.

7. From the proof to the code
ProofIn detectCycle
both pointers start at headslow = fast = head
after sss rounds, 1 step and 2 stepsslow = slow.next and fast = fast.next.next
the meeting, after s=k⋅Ls = k \cdot Ls=k⋅L roundsif slow == fast:
no cycle: fast reaches the endwhile fast and fast.next: then return None
walk aaa steps from head and from the meeting pointptr1 = head, ptr2 = slow, then one step each per round
both arrive at the entrance togetherwhile ptr1 != ptr2: then return ptr1

Phase 1 takes at most a+La + La+L rounds and phase 2 takes aaa rounds, so the code takes O(n)O(n)O(n) time for a list of nnn nodes. It keeps four pointers, so it uses O(1)O(1)O(1) extra space and never changes the list.

Code Shape
Archetype Code Shape
Python
1if not head or not head.next:
2 return None
3slow = fast = head
4has_cycle = False
5while fast and fast.next:
6 slow = slow.next
7 fast = fast.next.next
8 if slow == fast:
9 has_cycle = True
10 break
11if not has_cycle:
12 return None
13ptr1 = head
14ptr2 = slow
15while ptr1 != ptr2:
16 ptr1 = ptr1.next
17 ptr2 = ptr2.next
18return ptr1

Conceptual Narrative

Detecting a cycle is the first step; finding its exact entrance needs the second phase of Floyd's algorithm, which rests on the equation L=k⋅C−xL = k \cdot C - xL=k⋅C−x.

🧭 Conceptual Foundation & Pattern Intuition

In Linked List Cycle I, we simply answered the binary question: does a cycle exist? We relied on the fact that within a cycle, a 2x runner gains 1 step per tick on a 1x runner, guaranteeing a collision. But knowing that a loop exists doesn't reveal where the straight track ends and the loop begins. Floyd's Phase 2 solves this without any extra memory (O(1)O(1)O(1) space) by exploiting an exact algebraic equivalence between the straightaway distance and the remaining loop distance.

🏟️ The Analogy: The Track with an Access Road

Imagine a running track shaped like the letter P or a lasso: a straight access road of length LLL leads to a circular track of circumference CCC. You and a friend start at the beginning of the road. Your friend runs twice as fast. When you both enter the circular track, your friend laps you and you collide at some point xxx steps past the entry gate. If someone now places a runner at the very beginning of the access road and tells both runners to jog forward at exactly 1 step per tick, they will arrive at the entry gate at the exact same second! The distance from the start of the road to the gate equals the remaining distance around the loop back to the gate.

🔑 Why It Works

Let:

  • LLL = distance from head to cycle entrance
  • CCC = circumference (length) of the cycle
  • xxx = distance from cycle entrance to the meeting point

When slow and fast collide:

  • slow traveled: dslow=L+xd_{slow} = L + xdslow​=L+x
  • fast traveled: dfast=L+k⋅C+xd_{fast} = L + k \cdot C + xdfast​=L+k⋅C+x (where k≥1k \ge 1k≥1 is the number of full laps fast ran)
  • Since fast travels at double speed: dfast=2⋅dslowd_{fast} = 2 \cdot d_{slow}dfast​=2⋅dslow​ (or 2(L+x)=L+k⋅C+x2(L + x) = L + k \cdot C + x2(L+x)=L+k⋅C+x)
  • Simplifying: 2L+2x=L+k⋅C+x  ⟹  2L + 2x = L + k \cdot C + x \implies2L+2x=L+k⋅C+x⟹ L=k⋅C−xL = k \cdot C - xL=k⋅C−x

What does k⋅C−xk \cdot C - xk⋅C−x mean? It is the exact remaining distance from the meeting point around the cycle back to the entrance gate! Therefore, walking LLL steps from head and walking LLL steps from the collision point (slow) brings both pointers to the cycle entrance simultaneously.

  • Advancing pointers at different speeds in Phase 2: In Phase 2, both p1 (from head) and p2 (from meeting point) must move at exactly 1 step per tick. Moving either at speed 2 skips the rendezvous point.

  • Returning boolean instead of node: LC 142 requires returning the ListNode object where the cycle begins, or None if no cycle exists.

  • Failing to return None on acyclic lists: If fast or fast.next reaches None, terminate and return None immediately before initiating Phase 2.

  • Floyd's Cycle Origin: pointer resets and phase 2 speed. In LC 142 (Linked List Cycle II), after the fast and slow pointers collide in Phase 1, you must reset ONE pointer to head and leave the other at the collision node, advancing both at 1 step per tick. Resetting both to head re-runs Phase 1 indefinitely; keeping fast at 2x speed causes them to overshoot and cycle past each other.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

"Return the node where the cycle begins" and a follow-up asking for O(1) memory: a list that may loop, and no room for a visited set. That is Fast & Slow Pointers, plus a second walk to find the entrance.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

fast has always taken twice as many steps as slow, so inside the cycle the gap closes by one per move and they must meet. From there, the cycle's first node is as far from the meeting point as from head, up to whole laps (L = k·C - d, derived in the invariant cards below).

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • while fast and fast.next: testing only fast crashes on fast.next.next for every list without a cycle that has an odd number of nodes.

  • if not has_cycle: return None before phase 2: when fast runs off the end there is no cycle, and phase 2 would walk into None.

  • Phase 2 moves ptr1 and ptr2 one step each: keeping ptr2 at two steps is not guaranteed to stop at the entrance.

The 60-Second Interview Pitch

Say this out loud before you type a single line

"I'd use Fast & Slow Pointers in two phases. First slow moves one step and fast two; inside a cycle fast gains exactly one step per move, so it can't jump over slow and they meet. If fast runs off the end, there's no cycle and I return None. Then I start ptr1 at head and ptr2 at the meeting point and move both one step at a time: the cycle's first node is as far from the meeting point as from head, up to whole laps, so they meet exactly there. The trap is the loop test: while fast and fast.next, or fast.next.next crashes on a list without a cycle. It's O(N) time and O(1) extra space."

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

Look at the execution steps: Phase 1 meets within at most C steps after slow enters loop (at most N steps). Phase 2 takes L steps to reach cycle origin. Total steps <= 2N = O(N).

SPACE COMPLEXITY

O(1) Auxiliary

Look at memory allocations: Call stack uses O(1) Iterative. Only stores two pointer references in O(1) auxiliary space.

Formal Recurrence Relation

T(N)=Phase1+Phase2≤N+N=O(N)T(N) = Phase1 + Phase2 \le N + N = O(N)T(N)=Phase1+Phase2≤N+N=O(N)

Derivation Progression

Phase 1 Collision

T1≤L+C≤NT1 \le L + C \le NT1≤L+C≤N

Fast pointer gains 1 node per step on slow inside the cycle.

Phase 2 Origin Rendezvous

T2=L≤NT2 = L \le NT2=L≤N

Both pointers move at 1 step per iteration across distance L.

Total Time Complexity

O(N) total steps

Strict linear runtime without modifying list nodes.

Variable Definitions

NNN

Total number of nodes in the linked list

LLL

Distance from head to cycle entrance

CCC

Circumference / length of the cycle

Memory Architecture & Bounds

🟣 Call Stack

O(1) Iterative

🔵 Auxiliary Heap

O(1) Pointer references only

🟢 Output Space

O(1) Single node reference

Boundary Best / Worst Cases

Best Case

O(1)O(1)O(1) only for 0 or 1 node; a list without a cycle still costs O(N)O(N)O(N) (fast walks to the end, about N/2N/2N/2 steps).

Average Case

O(N)O(N)O(N).

Worst Case

O(N)O(N)O(N) full traversal.

Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "return the node where the cycle begins", "do not modify the linked list", "O(1) memory". A list that may loop and no room for a visited set: Fast & Slow Pointers, then a second walk from head to find the entrance.

CONSTRAINTS & BOUNDS

0≤N≤1040 \le N \le 10^40≤N≤104 nodes. A visited set also runs in O(N)O(N)O(N) time but stores up to NNN node references; the follow-up asks for O(1)O(1)O(1) memory, which only the two-speed walk gives.

FAANG PRODUCTION TRAPS & EDGE CASES

At scale: when each hop is expensive (following a redirect, a symlink or a reference stored on another machine), fast pays two hops per move, so phase 1 costs about three hops per step of slow; that is still far cheaper in memory than remembering every hop, which a long or endless chain can exhaust.

Core Algorithmic State Invariants

  1. Why the Second Walk Stops at the Entrance

Let L be the distance from head to the cycle's first node, d the distance from there to the meeting point, and C the cycle length. At the meeting, fast has walked twice as far as slow, so 2(L + d) = L + d + k·C for some whole number of laps k, which gives L = k·C - d. From the meeting point, L steps are k·C - d steps: d short of k full laps, which is exactly the cycle's first node. So ptr1 from head and ptr2 from the meeting point, one step each, arrive there together after L steps.

Theory Context•Two Pointers & Sliding Window
MediumLC 142

Linked List Cycle II (LeetCode 142)

Target Frequency:AmazonMicrosoftGoogle

You're given the head of a linked list that may loop back on itself. Find and return the exact node where that loop begins — or null if the list has no loop at all.

(A test harness may describe the loop internally with a 0-indexed pos marking where the tail's next pointer reconnects, using -1 for no loop, but that index is never handed to your function.)

You must leave the linked list unmodified.

Worked Examples

Example 1
Input:head = [3,2,0,-4], pos = 1
Output:tail connects to node index 1
Cyclic Linked List TopologyCycle at Node[1]
Floyd Cycle Detection
Access Road (L):1 node
Cycle Loop (C):3 nodes
Loop Entry:Node[1] (val: 2)
Collision / Meeting Point Detected!
3[0] head🐢 slow🐇 fast2[1] 0[2] -4[3] tailnext = Node[1]
Fast / Slow Pointer Invariant

Slow advances 1 step (slow = slow.next) while Fast advances 2 steps (fast = fast.next.next). The distance between them decreases by 1 on every cycle iteration.

Cycle Origin Recovery ($L = kC - M$)

Upon collision inside the loop, moving one pointer back to the list head and advancing both at 1 step guarantees they will collide at the exact cycle entrance node.

320-4
Explanation: The tail node (-4) loops back into the node at index 1 (value 2), so that node is the cycle's entry point.
Example 2
Input:head = [1,2], pos = 0
Output:tail connects to node index 0
12
Explanation: The tail node (2) loops back into the node at index 0 (value 1), so that node is the cycle's entry point.
Example 3
Input:head = [1], pos = -1
Output:no cycle
1
Explanation: There is no cycle in the linked list.

⚖️Formal Constraints & Bounds

  • The number of the nodes in the list is in the range [0, 104].

  • -105 <= Node.val <= 105

  • pos is -1 or a valid index in the linked-list.

Deep-Dive & Conceptual Insights

Core Insight

The distance from the head to the cycle origin equals the distance from the Phase 1 collision point to the cycle origin (L = k·C - x).

Real-World Scenario & Production Applications

Detecting circular dependencies in build systems, finding recurring loop states in state machines, and reference-counted garbage collection.

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Phase 1 -- Fast & Slow Pointer Collision

Advance slow at 1x speed and fast at 2x speed until they collide inside the cycle loop, proving a cycle exists. If fast reaches null, terminate early.

Mathematical Recurrence / Code Invariant
slow, fast = head, head
while fast and fast.next:
    slow = slow.next; fast = fast.next.next
    if slow == fast: break
else: return None

Step-by-Step Execution Trace Table

PhaseStepPtr 1 PositionPtr 2 PositionDistance / ActionStatus
Phase 1: Rendezvous1-3slow at Node(-4)fast at Node(-4)Standard Floyd cycle detectionRendezvous confirmed at Node(-4)
Phase 2: Origin SeekInitp1 = head (Node 3)p2 = meeting (Node -4)Reset one pointer to head; keep other at meeting nodeBoth step at uniform speed 1
Phase 2: Origin Seek1p1 = p1.next (Node 2)p2 = p2.next (Node 2)Step 1: 3 -> 2; -4 -> 2p1 == p2! Cycle entry is Node(2)
Worked on Paper

The Math, Step by Step

1. The distances in the list

Count distances in steps, where one step follows one next pointer. Name three numbers:

  • aaa is the number of steps from head to the entrance, the first node of the cycle. This is the node the code must return.
  • LLL is the cycle length, the number of nodes in the cycle. Walking LLL steps inside the cycle brings you back to the same node.
  • bbb is the number of steps from the entrance forward to the node where slow and fast meet, with 0≤b<L0 \le b < L0≤b<L.
320-4

The picture shows Example 1. The tail node −4-4−4 points back to the node with value 2 at index 1. So the entrance is index 1, a=1a = 1a=1, and the cycle holds the three nodes 2, 0 and −4-4−4, so L=3L = 3L=3.

2. Where the two pointers are after sss rounds

Both pointers start at head. In every round of phase 1, slow moves 1 step and fast moves 2 steps. After sss rounds, slow has moved sss steps and fast has moved 2s2s2s steps.

The number of steps a pointer has moved decides where it stands. A pointer that moved fewer than aaa steps is still before the cycle. A pointer that moved t≥at \ge at≥a steps is inside the cycle, (t−a) mod L(t - a) \bmod L(t−a)modL steps past the entrance. Here x mod Lx \bmod LxmodL is the remainder after dividing xxx by LLL.

3. Why phase 2 stops at the entrance

Suppose the pointers meet after sss rounds. They stand on the same node inside the cycle. fast has moved sss steps more than slow. Two positions in the cycle are the same only when the difference in steps is a whole number of laps. So

s=k⋅Lfor some whole number k≥1s = k \cdot L \quad \text{for some whole number } k \ge 1s=k⋅Lfor some whole number k≥1

slow stands bbb steps past the entrance, so s−as - as−a and bbb differ by whole laps: s−a=b+j⋅Ls - a = b + j \cdot Ls−a=b+j⋅L for some whole number j≥0j \ge 0j≥0. Put s=k⋅Ls = k \cdot Ls=k⋅L into this equation:

a+b=(k−j)⋅La + b = (k - j) \cdot La+b=(k−j)⋅L

So a+ba + ba+b is a whole number of laps. This is the key fact: walking aaa steps forward from the meeting point ends at the entrance. The meeting point is bbb steps past the entrance. Walking aaa more steps puts a pointer a+ba + ba+b steps past the entrance, which is a whole number of laps, so it is at the entrance again.

Phase 2 uses this fact. ptr1 starts at head, and ptr2 starts at the meeting point. Both move one step per round. After aaa rounds, ptr1 reaches the entrance, because the entrance is aaa steps from head. ptr2 also reaches the entrance, by the key fact. They cannot meet earlier. Before round aaa, ptr1 is still outside the cycle, and ptr2 is always inside it.

4. Why phase 1 always ends, and the start at head

If the list has no cycle, fast reaches the end first. The loop while fast and fast.next stops, and the code returns None.

If the list has a cycle, slow enters it after aaa rounds. fast is already inside. From then on, fast gains one step on slow in every round. The gap between them inside the cycle shrinks by one step per round, so it reaches 000 within LLL rounds. So phase 1 ends after at most a+La + La+L rounds.

Both pointers must start at the same node, head. The proof in part 3 uses "fast has moved exactly twice as many steps as slow". If fast started at head.next, that rule would be off by one step. On Example 1 the two pointers of phase 2 would then never stand on the same node, so the loop while ptr1 != ptr2 would never end.

5. Example 1 by hand

head = [3,2,0,-4], pos = 1, so a=1a = 1a=1 and L=3L = 3L=3. Nodes are named by index.

Roundslow movedslow atfast movedfast at
11index 1 (value 2)2index 2 (value 0)
22index 2 (value 0)4index 1 (value 2)
33index 3 (value −4-4−4)6index 3 (value −4-4−4)

The pointers meet after s=3s = 3s=3 rounds, which is 1⋅L1 \cdot L1⋅L. The meeting node, index 3, is b=2b = 2b=2 steps past the entrance. So a+b=1+2=3=La + b = 1 + 2 = 3 = La+b=1+2=3=L, a whole lap. In phase 2, ptr1 moves from index 0 to index 1, and ptr2 moves from index 3 to index 1. They meet after a=1a = 1a=1 round, at index 1. That is the expected output: the tail connects to node index 1.

6. Example 2 by hand

head = [1,2], pos = 0, so a=0a = 0a=0 and L=2L = 2L=2. After round 1, slow is at index 1 and fast is at index 0. After round 2, both are at index 0, so s=2=1⋅Ls = 2 = 1 \cdot Ls=2=1⋅L and b=0b = 0b=0. In phase 2, ptr1 starts at head, index 0, and ptr2 starts at the meeting point, also index 0. The loop while ptr1 != ptr2 runs zero rounds, and the code returns index 0, the expected output. This matches a=0a = 0a=0.

7. From the proof to the code
ProofIn detectCycle
both pointers start at headslow = fast = head
after sss rounds, 1 step and 2 stepsslow = slow.next and fast = fast.next.next
the meeting, after s=k⋅Ls = k \cdot Ls=k⋅L roundsif slow == fast:
no cycle: fast reaches the endwhile fast and fast.next: then return None
walk aaa steps from head and from the meeting pointptr1 = head, ptr2 = slow, then one step each per round
both arrive at the entrance togetherwhile ptr1 != ptr2: then return ptr1

Phase 1 takes at most a+La + La+L rounds and phase 2 takes aaa rounds, so the code takes O(n)O(n)O(n) time for a list of nnn nodes. It keeps four pointers, so it uses O(1)O(1)O(1) extra space and never changes the list.

Code Shape
Archetype Code Shape
Python
1if not head or not head.next:
2 return None
3slow = fast = head
4has_cycle = False
5while fast and fast.next:
6 slow = slow.next
7 fast = fast.next.next
8 if slow == fast:
9 has_cycle = True
10 break
11if not has_cycle:
12 return None
13ptr1 = head
14ptr2 = slow
15while ptr1 != ptr2:
16 ptr1 = ptr1.next
17 ptr2 = ptr2.next
18return ptr1

Conceptual Narrative

Detecting a cycle is the first step; finding its exact entrance needs the second phase of Floyd's algorithm, which rests on the equation L=k⋅C−xL = k \cdot C - xL=k⋅C−x.

🧭 Conceptual Foundation & Pattern Intuition

In Linked List Cycle I, we simply answered the binary question: does a cycle exist? We relied on the fact that within a cycle, a 2x runner gains 1 step per tick on a 1x runner, guaranteeing a collision. But knowing that a loop exists doesn't reveal where the straight track ends and the loop begins. Floyd's Phase 2 solves this without any extra memory (O(1)O(1)O(1) space) by exploiting an exact algebraic equivalence between the straightaway distance and the remaining loop distance.

🏟️ The Analogy: The Track with an Access Road

Imagine a running track shaped like the letter P or a lasso: a straight access road of length LLL leads to a circular track of circumference CCC. You and a friend start at the beginning of the road. Your friend runs twice as fast. When you both enter the circular track, your friend laps you and you collide at some point xxx steps past the entry gate. If someone now places a runner at the very beginning of the access road and tells both runners to jog forward at exactly 1 step per tick, they will arrive at the entry gate at the exact same second! The distance from the start of the road to the gate equals the remaining distance around the loop back to the gate.

🔑 Why It Works

Let:

  • LLL = distance from head to cycle entrance
  • CCC = circumference (length) of the cycle
  • xxx = distance from cycle entrance to the meeting point

When slow and fast collide:

  • slow traveled: dslow=L+xd_{slow} = L + xdslow​=L+x
  • fast traveled: dfast=L+k⋅C+xd_{fast} = L + k \cdot C + xdfast​=L+k⋅C+x (where k≥1k \ge 1k≥1 is the number of full laps fast ran)
  • Since fast travels at double speed: dfast=2⋅dslowd_{fast} = 2 \cdot d_{slow}dfast​=2⋅dslow​ (or 2(L+x)=L+k⋅C+x2(L + x) = L + k \cdot C + x2(L+x)=L+k⋅C+x)
  • Simplifying: 2L+2x=L+k⋅C+x  ⟹  2L + 2x = L + k \cdot C + x \implies2L+2x=L+k⋅C+x⟹ L=k⋅C−xL = k \cdot C - xL=k⋅C−x

What does k⋅C−xk \cdot C - xk⋅C−x mean? It is the exact remaining distance from the meeting point around the cycle back to the entrance gate! Therefore, walking LLL steps from head and walking LLL steps from the collision point (slow) brings both pointers to the cycle entrance simultaneously.

  • Advancing pointers at different speeds in Phase 2: In Phase 2, both p1 (from head) and p2 (from meeting point) must move at exactly 1 step per tick. Moving either at speed 2 skips the rendezvous point.

  • Returning boolean instead of node: LC 142 requires returning the ListNode object where the cycle begins, or None if no cycle exists.

  • Failing to return None on acyclic lists: If fast or fast.next reaches None, terminate and return None immediately before initiating Phase 2.

  • Floyd's Cycle Origin: pointer resets and phase 2 speed. In LC 142 (Linked List Cycle II), after the fast and slow pointers collide in Phase 1, you must reset ONE pointer to head and leave the other at the collision node, advancing both at 1 step per tick. Resetting both to head re-runs Phase 1 indefinitely; keeping fast at 2x speed causes them to overshoot and cycle past each other.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

"Return the node where the cycle begins" and a follow-up asking for O(1) memory: a list that may loop, and no room for a visited set. That is Fast & Slow Pointers, plus a second walk to find the entrance.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

fast has always taken twice as many steps as slow, so inside the cycle the gap closes by one per move and they must meet. From there, the cycle's first node is as far from the meeting point as from head, up to whole laps (L = k·C - d, derived in the invariant cards below).

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • while fast and fast.next: testing only fast crashes on fast.next.next for every list without a cycle that has an odd number of nodes.

  • if not has_cycle: return None before phase 2: when fast runs off the end there is no cycle, and phase 2 would walk into None.

  • Phase 2 moves ptr1 and ptr2 one step each: keeping ptr2 at two steps is not guaranteed to stop at the entrance.

The 60-Second Interview Pitch

Say this out loud before you type a single line

"I'd use Fast & Slow Pointers in two phases. First slow moves one step and fast two; inside a cycle fast gains exactly one step per move, so it can't jump over slow and they meet. If fast runs off the end, there's no cycle and I return None. Then I start ptr1 at head and ptr2 at the meeting point and move both one step at a time: the cycle's first node is as far from the meeting point as from head, up to whole laps, so they meet exactly there. The trap is the loop test: while fast and fast.next, or fast.next.next crashes on a list without a cycle. It's O(N) time and O(1) extra space."

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

Look at the execution steps: Phase 1 meets within at most C steps after slow enters loop (at most N steps). Phase 2 takes L steps to reach cycle origin. Total steps <= 2N = O(N).

SPACE COMPLEXITY

O(1) Auxiliary

Look at memory allocations: Call stack uses O(1) Iterative. Only stores two pointer references in O(1) auxiliary space.

Formal Recurrence Relation

T(N)=Phase1+Phase2≤N+N=O(N)T(N) = Phase1 + Phase2 \le N + N = O(N)T(N)=Phase1+Phase2≤N+N=O(N)

Derivation Progression

Phase 1 Collision

T1≤L+C≤NT1 \le L + C \le NT1≤L+C≤N

Fast pointer gains 1 node per step on slow inside the cycle.

Phase 2 Origin Rendezvous

T2=L≤NT2 = L \le NT2=L≤N

Both pointers move at 1 step per iteration across distance L.

Total Time Complexity

O(N) total steps

Strict linear runtime without modifying list nodes.

Variable Definitions

NNN

Total number of nodes in the linked list

LLL

Distance from head to cycle entrance

CCC

Circumference / length of the cycle

Memory Architecture & Bounds

🟣 Call Stack

O(1) Iterative

🔵 Auxiliary Heap

O(1) Pointer references only

🟢 Output Space

O(1) Single node reference

Boundary Best / Worst Cases

Best Case

O(1)O(1)O(1) only for 0 or 1 node; a list without a cycle still costs O(N)O(N)O(N) (fast walks to the end, about N/2N/2N/2 steps).

Average Case

O(N)O(N)O(N).

Worst Case

O(N)O(N)O(N) full traversal.

Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "return the node where the cycle begins", "do not modify the linked list", "O(1) memory". A list that may loop and no room for a visited set: Fast & Slow Pointers, then a second walk from head to find the entrance.

CONSTRAINTS & BOUNDS

0≤N≤1040 \le N \le 10^40≤N≤104 nodes. A visited set also runs in O(N)O(N)O(N) time but stores up to NNN node references; the follow-up asks for O(1)O(1)O(1) memory, which only the two-speed walk gives.

FAANG PRODUCTION TRAPS & EDGE CASES

At scale: when each hop is expensive (following a redirect, a symlink or a reference stored on another machine), fast pays two hops per move, so phase 1 costs about three hops per step of slow; that is still far cheaper in memory than remembering every hop, which a long or endless chain can exhaust.

Core Algorithmic State Invariants

  1. Why the Second Walk Stops at the Entrance

Let L be the distance from head to the cycle's first node, d the distance from there to the meeting point, and C the cycle length. At the meeting, fast has walked twice as far as slow, so 2(L + d) = L + d + k·C for some whole number of laps k, which gives L = k·C - d. From the meeting point, L steps are k·C - d steps: d short of k full laps, which is exactly the cycle's first node. So ptr1 from head and ptr2 from the meeting point, one step each, arrive there together after L steps.

© 2026 Hi👋WebEnterprise. All rights reserved.
Sitemap•llms.txt•