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•Math & Geometry
MediumLC 1823

Find the Winner of the Circular Game (LeetCode 1823)

Target Frequency:GoogleAppleNetflix

n friends sit around a circle, labeled 1 through n going clockwise, so stepping clockwise past friend n wraps you straight back to friend 1.

Play unfolds like this:

  • Everyone begins with friend 1 as the current spot.
  • From there, tick off k friends moving clockwise, counting the current friend as the first tick -- looping around the circle again if k is larger than however many friends remain.
  • Whichever friend the k-th tick lands on is eliminated and steps out of the circle.
  • As long as two or more friends remain, the next round starts its count from the friend standing immediately clockwise of the one who just left.
  • Once only one friend is left, that friend is declared the winner.

Given n and k, work out which friend wins.

Worked Examples

Example 1
Input:n = 5, k = 2
Output:3
1021324354winner
Explanation: Tracking each round: (1) counting 1,2 from friend 1 eliminates 2, next count starts at 3; (2) counting 3,4 eliminates 4, next count starts at 5; (3) counting 5,1 eliminates 1, next count starts at 3; (4) counting 3,5 eliminates 5, leaving only friend 3, so friend 3 wins.
Example 2
Input:n = 6, k = 5
Output:1
102132435465winner
Explanation: Elimination order across the rounds is 5, then 4, then 6, then 2, then 3, which leaves friend 1 as the sole survivor and winner.

⚖️Formal Constraints & Bounds

  • 1 <= k <= n <= 500

Deep-Dive & Conceptual Insights

Core Insight

Simulating circular array deletion takes O(n * k) or O(n^2) time. The subproblem recurrence f(n, k) = (f(n - 1, k) + k) % n computes the answer iteratively in O(N) time with O(1) extra space.

Real-World Scenario & Production Applications

Counting-out games, where players stand in a circle and every k-th player drops out until one is left, like a playground rhyme that picks who is "it".

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Base Case -- A Single Survivor

With exactly 1 person in the circle, position 0 (0-indexed) trivially wins -- there's no one else to eliminate.

Mathematical Recurrence / Code Invariant
if n == 1:
    return 0

Step-by-Step Execution Trace Table

Iteration i (Circle Size)Subproblem State f(i, k)Shift (+ k)Modulo (% i)Winner (0-indexed)
1Base case (single person)00 % 1 = 00
2(0 + 2) % 222 % 2 = 00
3(0 + 2) % 322 % 3 = 22
4(2 + 2) % 444 % 4 = 00
5(0 + 2) % 522 % 5 = 22 (1-indexed -> 3)
Worked on Paper

The Math, Step by Step

1. The winner as a seat number from 0

Number the seats from 0 instead of from 1: friend fff sits at seat f−1f - 1f−1. Write J(s)J(s)J(s) for the seat of the winner in a game with sss friends that starts counting at seat 0. The answer to the problem is J(n)+1J(n) + 1J(n)+1.

A game with one friend needs no round, so J(1)=0J(1) = 0J(1)=0.

2. What the first round does

In a game of sss friends, the count starts at seat 0 and ticks off kkk friends. The kkk-th tick lands on seat (k−1) mod s(k - 1) \bmod s(k−1)mods, and that friend leaves. Here x mod sx \bmod sxmods is the remainder after dividing xxx by sss, which wraps the count around the circle. The next round starts at the seat right after it, seat k mod sk \bmod skmods.

Now s−1s - 1s−1 friends are left, and the next count starts at seat k mod sk \bmod skmods. This is a new game of s−1s - 1s−1 friends. Give its seats new numbers, starting with 0 at seat k mod sk \bmod skmods:

New seat in the game of s−1s - 1s−1Old seat in the game of sss
0k mod sk \bmod skmods
1(k+1) mod s(k + 1) \bmod s(k+1)mods
www(w+k) mod s(w + k) \bmod s(w+k)mods

The new numbering has seats 0 to s−2s - 2s−2. A new seat s−1s - 1s−1 would be old seat (s−1+k) mod s=(k−1) mod s(s - 1 + k) \bmod s = (k - 1) \bmod s(s−1+k)mods=(k−1)mods, the friend who left, so it is not part of the smaller game.

3. The recurrence

The smaller game follows exactly the same rules, so its winner sits at new seat J(s−1)J(s - 1)J(s−1). The table turns that into an old seat:

J(s)=(J(s−1)+k) mod sJ(s) = \big(J(s - 1) + k\big) \bmod sJ(s)=(J(s−1)+k)mods

Starting from J(1)=0J(1) = 0J(1)=0, the code applies this rule for s=2,3,…,ns = 2, 3, \ldots, ns=2,3,…,n. It never simulates the circle. This is the Josephus recurrence.

4. Why the seats count from 0

The mod of part 3 only works with seats numbered from 0. The remainder x mod sx \bmod sxmods is always between 0 and s−1s - 1s−1, which are exactly the seat numbers. With seats numbered from 1, a remainder of 0 would name a seat that does not exist. So the code works with JJJ from 0 and adds 1 only at the end, in return winner + 1.

kkk may be larger than the number of friends left, for example k=5k = 5k=5 with 2 friends. The mod handles this, because counting past the last seat wraps to the first.

5. Example 1 by hand

n = 5, k = 2.

sizewinner beforewinner + kwinner = (winner + k) % size
2022 mod 2=02 \bmod 2 = 02mod2=0
3022 mod 3=22 \bmod 3 = 22mod3=2
4244 mod 4=04 \bmod 4 = 04mod4=0
5022 mod 5=22 \bmod 5 = 22mod5=2

J(5)=2J(5) = 2J(5)=2, so the code returns 2+1=32 + 1 = 32+1=3, the expected output. A direct simulation removes friends 2, 4, 1 and 5, and friend 3 is left, which agrees.

6. Example 2 by hand

n = 6, k = 5.

sizewinner beforewinner + kwinner = (winner + k) % size
2055 mod 2=15 \bmod 2 = 15mod2=1
3166 mod 3=06 \bmod 3 = 06mod3=0
4055 mod 4=15 \bmod 4 = 15mod4=1
5166 mod 5=16 \bmod 5 = 16mod5=1
6166 mod 6=06 \bmod 6 = 06mod6=0

J(6)=0J(6) = 0J(6)=0, so the code returns 0+1=10 + 1 = 10+1=1, the expected output. A direct simulation removes friends 5, 4, 6, 2 and 3, and friend 1 is left.

7. From the math to the code
MathIn findTheWinner
J(1)=0J(1) = 0J(1)=0winner = 0
s=2,3,…,ns = 2, 3, \ldots, ns=2,3,…,nfor size in range(2, n + 1):
J(s)=(J(s−1)+k) mod sJ(s) = (J(s - 1) + k) \bmod sJ(s)=(J(s−1)+k)modswinner = (winner + k) % size
friend number J(n)+1J(n) + 1J(n)+1return winner + 1

The loop runs n−1n - 1n−1 times with one addition and one remainder each, so the code takes O(n)O(n)O(n) time and O(1)O(1)O(1) space.

Code Shape
Archetype Code Shape
Python
1winner = 0
2for size in range(2, n + 1):
3 winner = (winner + k) % size
4return winner + 1

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

Simulating the entire circle of friends being eliminated one by one feels like the obvious approach — but this solution never simulates a single elimination. It builds the answer backward, from the smallest possible circle up.

🔄 The Analogy: Rewind, Then Fast-Forward One Person at a Time

Start from the trivial case: with just 1 friend in the circle, that friend obviously wins — position 0. Now imagine you already know the winning position for a circle of size - 1 friends. What happens when you add one more friend to make a circle of size? The entire elimination pattern is identical to before — it's just been rotated by k seats, and wrapped around a slightly bigger circle. So the new winner's seat is simply the old winner's seat, shifted by k, wrapped around using the new, larger circle size.

You never touch a real elimination — you just replay "shift by k, wrap around" one circle-size at a time, growing the circle from 1 person up to n.

🔑 The Key Idea in the Code

Each loop iteration answers "if I already know the winner for a circle of size - 1 friends, what's the winner for a circle of size friends?" — a single O(1) rotation, repeated n - 1 times, instead of an O(N·K) simulation of the whole game.

  • 1-indexed to 0-indexed conversion off-by-one: The mathematical recurrence f(n,k)=(f(n−1,k)+k)(modn)f(n, k) = (f(n-1, k) + k) \pmod nf(n,k)=(f(n−1,k)+k)(modn) operates on 0-indexed positions. Forgetting to add +1+1+1 at the final return violates 1-indexed output requirements.

  • Simulating with list deletion taking O(N2)O(N^2)O(N2) time: Simulating circle elimination with list.pop(index) takes O(N2)O(N^2)O(N2) time due to array element shifts. The bottom-up iterative DP formula computes the survivor in O(N)O(N)O(N) time and O(1)O(1)O(1) space.

  • Base case n=1n = 1n=1: winner starts at 0, the seat of the only friend counted from 0; the function still returns winner + 1 = 1.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

"n friends sit around a circle", "the k-th tick ... is eliminated and steps out of the circle", "the next round starts its count from the friend standing immediately clockwise" and "once only one friend is left, that friend is declared the winner": every k-th one leaves a circle and only the last one is asked for. That is the Josephus Problem: solve the smaller circle, then shift its answer.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Invariant: winner is the 0-indexed seat of the winner for size friends. Going from size - 1 to size friends shifts that seat by k: winner = (winner + k) % size.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • The card's trap: start from winner = 0 and add 1 only in the final return.

  • k can be larger than the circle (up to n): (winner + k) % size already counts whole laps, so no special case is needed.

The 60-Second Interview Pitch

Say this out loud before you type a single line

I'd use the Josephus recurrence. Once the first friend leaves, what's left is the same game with one friend fewer, only started k seats later. So if winner is the 0-indexed winner for size - 1 friends, the winner for size friends is (winner + k) % size. That's correct because removing the k-th friend and restarting from the next seat is exactly the smaller circle shifted by k seats, and % size wraps the shift around the bigger circle. I start with winner = 0 for one friend and loop size from 2 up to n. The trap is the index base: the recurrence counts seats from 0 but the friends are numbered from 1, so I add 1 only in the final return. That's O(N) time and O(1) space.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

Look at the execution steps: Bottom-up Josephus recurrence: f(1) = 0, f(i) = (f(i-1) + k) % i for i from 2 to N. Single linear for-loop with N - 1 arithmetic updates.

SPACE COMPLEXITY

O(1) Auxiliary

Look at memory allocations: Call stack uses O(1) Iterative. Single scalar integer register storing winner index in O(1) space.

Formal Recurrence Relation

T(N)=N−1 modulo additions=O(N)T(N) = N - 1 \text{ modulo additions} = O(N)T(N)=N−1 modulo additions=O(N)

Derivation Progression

Base Case

f(1) = 0

With 1 person, winner is at 0-based index 0.

Index Shift Recurrence

f(i) = (f(i-1) + k) (mod i)

Remaps winner index when subproblem size expands from i-1 to i.

Linear Loop

N-1 arithmetic steps = O(N)

Computes exact winner in single linear loop.

Variable Definitions

NNN

Total number of friends in the circular game

KKK

Step counting offset for eliminations

Memory Architecture & Bounds

🟣 Call Stack

O(1) Iterative

🔵 Auxiliary Heap

O(1) Single integer register

🟢 Output Space

O(1) 1-based winner integer

Boundary Best / Worst Cases

Best Case

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

Average Case

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

Worst Case

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

Recurrence Tree Topology

Recurrence Tree Topology
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Structural triggers: "clock-wise circular order", "eliminate every k-th friend", "last friend remaining". Direct simulation via linked list or array pop costs O(N⋅k)O(N \cdot k)O(N⋅k) or O(N2)O(N^2)O(N2) time. A Senior SWE immediately recognizes the historic Josephus Problem, solvable in O(N)O(N)O(N) time and O(1)O(1)O(1) space using bottom-up dynamic programming via cyclic coordinate shifting.

CONSTRAINTS & BOUNDS

1≤k≤n≤5001 \le k \le n \le 5001≤k≤n≤500: at most 499499499 constant-time updates, with no list of friends and no node allocation.

FAANG PRODUCTION TRAPS & EDGE CASES

With fixed-width integers, winner + k is below 2n2n2n, which only overflows a 32-bit int once nnn passes 2302^{30}230.

Core Algorithmic State Invariants

  1. Only the Winner Is Cheap

The recurrence tracks one seat, the winner's, so it never knows who left in which round. If a problem asks for the whole elimination order, you have to simulate the removals instead.

  1. k = 2 Has a Closed Form

For k = 2, write n = 2^m + L with 0 <= L < 2^m: the winner (numbered from 1) is 2L + 1. For n = 5 = 4 + 1 that is 3, which the loop also returns.

  1. Loop, Not Recursion

The same rule written top-down, f(size) = (f(size - 1) + k) % size, recurses n levels deep. The loop from size = 2 up to n gives the same answer with no call stack.

Theory Context•Math & Geometry
MediumLC 1823

Find the Winner of the Circular Game (LeetCode 1823)

Target Frequency:GoogleAppleNetflix

n friends sit around a circle, labeled 1 through n going clockwise, so stepping clockwise past friend n wraps you straight back to friend 1.

Play unfolds like this:

  • Everyone begins with friend 1 as the current spot.
  • From there, tick off k friends moving clockwise, counting the current friend as the first tick -- looping around the circle again if k is larger than however many friends remain.
  • Whichever friend the k-th tick lands on is eliminated and steps out of the circle.
  • As long as two or more friends remain, the next round starts its count from the friend standing immediately clockwise of the one who just left.
  • Once only one friend is left, that friend is declared the winner.

Given n and k, work out which friend wins.

Worked Examples

Example 1
Input:n = 5, k = 2
Output:3
1021324354winner
Explanation: Tracking each round: (1) counting 1,2 from friend 1 eliminates 2, next count starts at 3; (2) counting 3,4 eliminates 4, next count starts at 5; (3) counting 5,1 eliminates 1, next count starts at 3; (4) counting 3,5 eliminates 5, leaving only friend 3, so friend 3 wins.
Example 2
Input:n = 6, k = 5
Output:1
102132435465winner
Explanation: Elimination order across the rounds is 5, then 4, then 6, then 2, then 3, which leaves friend 1 as the sole survivor and winner.

⚖️Formal Constraints & Bounds

  • 1 <= k <= n <= 500

Deep-Dive & Conceptual Insights

Core Insight

Simulating circular array deletion takes O(n * k) or O(n^2) time. The subproblem recurrence f(n, k) = (f(n - 1, k) + k) % n computes the answer iteratively in O(N) time with O(1) extra space.

Real-World Scenario & Production Applications

Counting-out games, where players stand in a circle and every k-th player drops out until one is left, like a playground rhyme that picks who is "it".

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Base Case -- A Single Survivor

With exactly 1 person in the circle, position 0 (0-indexed) trivially wins -- there's no one else to eliminate.

Mathematical Recurrence / Code Invariant
if n == 1:
    return 0

Step-by-Step Execution Trace Table

Iteration i (Circle Size)Subproblem State f(i, k)Shift (+ k)Modulo (% i)Winner (0-indexed)
1Base case (single person)00 % 1 = 00
2(0 + 2) % 222 % 2 = 00
3(0 + 2) % 322 % 3 = 22
4(2 + 2) % 444 % 4 = 00
5(0 + 2) % 522 % 5 = 22 (1-indexed -> 3)
Worked on Paper

The Math, Step by Step

1. The winner as a seat number from 0

Number the seats from 0 instead of from 1: friend fff sits at seat f−1f - 1f−1. Write J(s)J(s)J(s) for the seat of the winner in a game with sss friends that starts counting at seat 0. The answer to the problem is J(n)+1J(n) + 1J(n)+1.

A game with one friend needs no round, so J(1)=0J(1) = 0J(1)=0.

2. What the first round does

In a game of sss friends, the count starts at seat 0 and ticks off kkk friends. The kkk-th tick lands on seat (k−1) mod s(k - 1) \bmod s(k−1)mods, and that friend leaves. Here x mod sx \bmod sxmods is the remainder after dividing xxx by sss, which wraps the count around the circle. The next round starts at the seat right after it, seat k mod sk \bmod skmods.

Now s−1s - 1s−1 friends are left, and the next count starts at seat k mod sk \bmod skmods. This is a new game of s−1s - 1s−1 friends. Give its seats new numbers, starting with 0 at seat k mod sk \bmod skmods:

New seat in the game of s−1s - 1s−1Old seat in the game of sss
0k mod sk \bmod skmods
1(k+1) mod s(k + 1) \bmod s(k+1)mods
www(w+k) mod s(w + k) \bmod s(w+k)mods

The new numbering has seats 0 to s−2s - 2s−2. A new seat s−1s - 1s−1 would be old seat (s−1+k) mod s=(k−1) mod s(s - 1 + k) \bmod s = (k - 1) \bmod s(s−1+k)mods=(k−1)mods, the friend who left, so it is not part of the smaller game.

3. The recurrence

The smaller game follows exactly the same rules, so its winner sits at new seat J(s−1)J(s - 1)J(s−1). The table turns that into an old seat:

J(s)=(J(s−1)+k) mod sJ(s) = \big(J(s - 1) + k\big) \bmod sJ(s)=(J(s−1)+k)mods

Starting from J(1)=0J(1) = 0J(1)=0, the code applies this rule for s=2,3,…,ns = 2, 3, \ldots, ns=2,3,…,n. It never simulates the circle. This is the Josephus recurrence.

4. Why the seats count from 0

The mod of part 3 only works with seats numbered from 0. The remainder x mod sx \bmod sxmods is always between 0 and s−1s - 1s−1, which are exactly the seat numbers. With seats numbered from 1, a remainder of 0 would name a seat that does not exist. So the code works with JJJ from 0 and adds 1 only at the end, in return winner + 1.

kkk may be larger than the number of friends left, for example k=5k = 5k=5 with 2 friends. The mod handles this, because counting past the last seat wraps to the first.

5. Example 1 by hand

n = 5, k = 2.

sizewinner beforewinner + kwinner = (winner + k) % size
2022 mod 2=02 \bmod 2 = 02mod2=0
3022 mod 3=22 \bmod 3 = 22mod3=2
4244 mod 4=04 \bmod 4 = 04mod4=0
5022 mod 5=22 \bmod 5 = 22mod5=2

J(5)=2J(5) = 2J(5)=2, so the code returns 2+1=32 + 1 = 32+1=3, the expected output. A direct simulation removes friends 2, 4, 1 and 5, and friend 3 is left, which agrees.

6. Example 2 by hand

n = 6, k = 5.

sizewinner beforewinner + kwinner = (winner + k) % size
2055 mod 2=15 \bmod 2 = 15mod2=1
3166 mod 3=06 \bmod 3 = 06mod3=0
4055 mod 4=15 \bmod 4 = 15mod4=1
5166 mod 5=16 \bmod 5 = 16mod5=1
6166 mod 6=06 \bmod 6 = 06mod6=0

J(6)=0J(6) = 0J(6)=0, so the code returns 0+1=10 + 1 = 10+1=1, the expected output. A direct simulation removes friends 5, 4, 6, 2 and 3, and friend 1 is left.

7. From the math to the code
MathIn findTheWinner
J(1)=0J(1) = 0J(1)=0winner = 0
s=2,3,…,ns = 2, 3, \ldots, ns=2,3,…,nfor size in range(2, n + 1):
J(s)=(J(s−1)+k) mod sJ(s) = (J(s - 1) + k) \bmod sJ(s)=(J(s−1)+k)modswinner = (winner + k) % size
friend number J(n)+1J(n) + 1J(n)+1return winner + 1

The loop runs n−1n - 1n−1 times with one addition and one remainder each, so the code takes O(n)O(n)O(n) time and O(1)O(1)O(1) space.

Code Shape
Archetype Code Shape
Python
1winner = 0
2for size in range(2, n + 1):
3 winner = (winner + k) % size
4return winner + 1

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

Simulating the entire circle of friends being eliminated one by one feels like the obvious approach — but this solution never simulates a single elimination. It builds the answer backward, from the smallest possible circle up.

🔄 The Analogy: Rewind, Then Fast-Forward One Person at a Time

Start from the trivial case: with just 1 friend in the circle, that friend obviously wins — position 0. Now imagine you already know the winning position for a circle of size - 1 friends. What happens when you add one more friend to make a circle of size? The entire elimination pattern is identical to before — it's just been rotated by k seats, and wrapped around a slightly bigger circle. So the new winner's seat is simply the old winner's seat, shifted by k, wrapped around using the new, larger circle size.

You never touch a real elimination — you just replay "shift by k, wrap around" one circle-size at a time, growing the circle from 1 person up to n.

🔑 The Key Idea in the Code

Each loop iteration answers "if I already know the winner for a circle of size - 1 friends, what's the winner for a circle of size friends?" — a single O(1) rotation, repeated n - 1 times, instead of an O(N·K) simulation of the whole game.

  • 1-indexed to 0-indexed conversion off-by-one: The mathematical recurrence f(n,k)=(f(n−1,k)+k)(modn)f(n, k) = (f(n-1, k) + k) \pmod nf(n,k)=(f(n−1,k)+k)(modn) operates on 0-indexed positions. Forgetting to add +1+1+1 at the final return violates 1-indexed output requirements.

  • Simulating with list deletion taking O(N2)O(N^2)O(N2) time: Simulating circle elimination with list.pop(index) takes O(N2)O(N^2)O(N2) time due to array element shifts. The bottom-up iterative DP formula computes the survivor in O(N)O(N)O(N) time and O(1)O(1)O(1) space.

  • Base case n=1n = 1n=1: winner starts at 0, the seat of the only friend counted from 0; the function still returns winner + 1 = 1.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

"n friends sit around a circle", "the k-th tick ... is eliminated and steps out of the circle", "the next round starts its count from the friend standing immediately clockwise" and "once only one friend is left, that friend is declared the winner": every k-th one leaves a circle and only the last one is asked for. That is the Josephus Problem: solve the smaller circle, then shift its answer.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Invariant: winner is the 0-indexed seat of the winner for size friends. Going from size - 1 to size friends shifts that seat by k: winner = (winner + k) % size.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • The card's trap: start from winner = 0 and add 1 only in the final return.

  • k can be larger than the circle (up to n): (winner + k) % size already counts whole laps, so no special case is needed.

The 60-Second Interview Pitch

Say this out loud before you type a single line

I'd use the Josephus recurrence. Once the first friend leaves, what's left is the same game with one friend fewer, only started k seats later. So if winner is the 0-indexed winner for size - 1 friends, the winner for size friends is (winner + k) % size. That's correct because removing the k-th friend and restarting from the next seat is exactly the smaller circle shifted by k seats, and % size wraps the shift around the bigger circle. I start with winner = 0 for one friend and loop size from 2 up to n. The trap is the index base: the recurrence counts seats from 0 but the friends are numbered from 1, so I add 1 only in the final return. That's O(N) time and O(1) space.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

Look at the execution steps: Bottom-up Josephus recurrence: f(1) = 0, f(i) = (f(i-1) + k) % i for i from 2 to N. Single linear for-loop with N - 1 arithmetic updates.

SPACE COMPLEXITY

O(1) Auxiliary

Look at memory allocations: Call stack uses O(1) Iterative. Single scalar integer register storing winner index in O(1) space.

Formal Recurrence Relation

T(N)=N−1 modulo additions=O(N)T(N) = N - 1 \text{ modulo additions} = O(N)T(N)=N−1 modulo additions=O(N)

Derivation Progression

Base Case

f(1) = 0

With 1 person, winner is at 0-based index 0.

Index Shift Recurrence

f(i) = (f(i-1) + k) (mod i)

Remaps winner index when subproblem size expands from i-1 to i.

Linear Loop

N-1 arithmetic steps = O(N)

Computes exact winner in single linear loop.

Variable Definitions

NNN

Total number of friends in the circular game

KKK

Step counting offset for eliminations

Memory Architecture & Bounds

🟣 Call Stack

O(1) Iterative

🔵 Auxiliary Heap

O(1) Single integer register

🟢 Output Space

O(1) 1-based winner integer

Boundary Best / Worst Cases

Best Case

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

Average Case

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

Worst Case

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

Recurrence Tree Topology

Recurrence Tree Topology
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Structural triggers: "clock-wise circular order", "eliminate every k-th friend", "last friend remaining". Direct simulation via linked list or array pop costs O(N⋅k)O(N \cdot k)O(N⋅k) or O(N2)O(N^2)O(N2) time. A Senior SWE immediately recognizes the historic Josephus Problem, solvable in O(N)O(N)O(N) time and O(1)O(1)O(1) space using bottom-up dynamic programming via cyclic coordinate shifting.

CONSTRAINTS & BOUNDS

1≤k≤n≤5001 \le k \le n \le 5001≤k≤n≤500: at most 499499499 constant-time updates, with no list of friends and no node allocation.

FAANG PRODUCTION TRAPS & EDGE CASES

With fixed-width integers, winner + k is below 2n2n2n, which only overflows a 32-bit int once nnn passes 2302^{30}230.

Core Algorithmic State Invariants

  1. Only the Winner Is Cheap

The recurrence tracks one seat, the winner's, so it never knows who left in which round. If a problem asks for the whole elimination order, you have to simulate the removals instead.

  1. k = 2 Has a Closed Form

For k = 2, write n = 2^m + L with 0 <= L < 2^m: the winner (numbered from 1) is 2L + 1. For n = 5 = 4 + 1 that is 3, which the loop also returns.

  1. Loop, Not Recursion

The same rule written top-down, f(size) = (f(size - 1) + k) % size, recurses n levels deep. The loop from size = 2 up to n gives the same answer with no call stack.

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