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).

12 Core Algorithmic Patterns & 189 Practice Problems

  • 1. Two Pointers (10 Paradigms, 34 Problems): Converging pointers, sorted pair sums, container with most water, trapping rain water, 3Sum, plus the Sliding Window and Fast & Slow Pointers paradigms (Floyd cycle detection, monotonic window invariants, longest substrings, minimum window).
  • 2. Binary Search (8 Paradigms, 12 Problems): Monotonic predicate partitioning, boundary searching, rotated arrays, median of two sorted arrays, matrix median on value range.
  • 3. Bit Manipulation (5 Paradigms, 8 Problems): Bitmasking, XOR tricks, counting set bits, subset enumeration via bitmasks.
  • 4. Math & Geometry (7 Paradigms, 13 Problems): Sieve of Eratosthenes, integer/roman conversions, modular arithmetic, geometric simulation.
  • 5. Tree/Graph Depth-First Search (10 Paradigms, 19 Problems): Path sums, lowest common ancestor, tree diameter, subtree serialization, validating BSTs.
  • 6. Tree/Graph Breadth-First Search (4 Paradigms, 11 Problems): Level-order traversals, shortest path, rotting oranges, word ladders.
  • 7. Graphs (10 Paradigms, 18 Problems): Topological sort, cycle detection, Dijkstra, bipartite validation, network delay.
  • 8. Backtracking (6 Paradigms, 14 Problems): Subsets, permutations, combinations, constraint satisfaction, pruning, N-Queens.
  • 9. Dynamic Programming (11 Paradigms, 18 Problems): Memoization vs tabulation, knapsack, coin change, edit distance, longest common subsequence.
  • 10. Heap / Priority Queue (8 Paradigms, 10 Problems): Running medians, top-k elements, interval scheduling, IPO, k-way merges.
  • 11. Advanced Data Structures (6 Paradigms, 14 Problems): Trie, Union-Find, LRU Cache, LFU Cache, Monotonic Stacks.
  • 12. Intervals & Stack / Miscellaneous (11 Paradigms, 18 Problems): Merge intervals, daily temperatures, largest rectangle in histogram, trapping rain water via stack.

4-Stage Deliberate Practice Framework

  1. Stage 1 (Compare & Learn): Multi-language Rosetta Stone contrasting abstract invariants with concrete solutions across Python, C#, Java, TypeScript, C++, Go, and Rust.
  2. Stage 2 (Active Recall): Reconstruct algorithmic template invariants from memory with real-time feedback before looking at solutions.
  3. Stage 3 (Senior SWE AI Mock Coach): Simulated senior mock interview evaluating Big-O space/time tradeoffs, edge cases, and code reviews in Monaco Editor.
  4. Stage 4 (Solve on Your Own): Timed sandbox challenges verified against automated test suites in Python, C#, Java, and TypeScript.

Equipped with SM-2 Spaced Repetition Review Hub, Studio Cockpit workspace layout, and interactive study notes.

Pricing, Access & Commercial Terms

  • Core Curriculum: 100% Free. No credit card required.
  • Compute Coins: 40 free coins upon signup, +20 daily login bonus, +25 referral bonus.
  • 24-Hour AI Coaching Pass: 5 compute coins unlocks unlimited senior SWE AI coaching for a full 24 hours.
  • BYOK (Bring Your Own Key): Completely free unlimited AI coaching if using your own Gemini/OpenAI API key.
  • Refund & Subscription Policy: No recurring charges, no subscription traps, and no paid paywalls. Free tier provides full learning path.
  • Platform Operator: Hi👋WebEnterprise Inc. Support & policies at hispeedalgo.com.
Skip to main content
Hi👋SpeedAlgo

Invariant-First Algorithmic Mastery

201Items
Theory Context•Two Pointers & Sliding Window
HardLC 41

First Missing Positive (LeetCode 41)

You will see how an array of n values can serve as its own hash table: each value from 1 to n is swapped to index v - 1.

Target Frequency:AmazonGoogleMicrosoftMeta

You get an array of integers, nums, in no particular order. It may hold zeros, negative numbers, very large numbers and repeated values. Find the smallest positive whole number (1, 2, 3, ...) that does not appear anywhere in nums, and return it.

Your solution must run in O(n) time, where n is the length of nums, and use only O(1) extra memory beyond the input array. Changing the values inside nums is allowed.

Worked Examples

Example 1
Input:nums = [1,2,0]
Output:3
1021020: no home
Explanation: 1 and 2 are both there, so the first positive number that is absent is 3. The 0 is not positive and plays no part.
Example 2
Input:nums = [3,4,-1,1]
Output:2
3041-12131 present
Explanation: 1 is present but 2 is not. The -1 is ignored, and 3 and 4 do not matter once 2 is missing.
Example 3
Input:nums = [7,8,9,11,12]
Output:1
708192113124
Explanation: No value is 1, so 1 itself is the answer; every value is larger than the length of the array.

⚖️Formal Constraints & Bounds

  • 1 <= nums.length <= 105

  • -231 <= nums[i] <= 231 - 1

Deep-Dive & Conceptual Insights

Why It Works & Core Invariant

A value v from 1 to n belongs at index v - 1, so the array can be its own hash table: send each such value home, and the first index that does not hold its own value names the smallest missing positive. Every other value can be ignored, because the answer is always between 1 and n + 1.

Real-World Scenario & Production Applications

Handing out the lowest free number: POSIX requires open() to return the lowest file descriptor that is not in use, and seat, locker or worker-slot numbers are often reused the same way. The numbers in use already say which slot each one fills, so the first empty slot is the answer.

Step-by-Step Execution Trace Table

Example 2, nums = [3,4,-1,1] (n = 4):

StepiValue nums[i]Home nums[i] - 1 holdsActionnums after
103-1swap: 3 goes home to index 2[-1,4,3,1]
20-1(no home)stop: -1 is not in 1..4[-1,4,3,1]
3141swap: 4 goes home to index 3[-1,1,3,4]
411-1swap: 1 goes home to index 0[1,-1,3,4]
51-1(no home)stop[1,-1,3,4]
6233stop: the home already holds 3[1,-1,3,4]
7344stop: the home already holds 4[1,-1,3,4]
8scannums[0] = 1; nums[1] = -1, not 2return 2
Scroll horizontally to see all columns, or expand to full screen

Three swaps for four values: each swap put one value in its home for good. With a repeated value, such as the second 2 in [2,3,2,1], the home already holds a copy; the test nums[nums[i] - 1] != nums[i] stops there, while nums[i] != i + 1 would swap the two 2s forever.

Core Invariant Specification & Code Shape
Archetype Code Shape
Python
1A value `v` from 1 to `n` has a home, index `v - 1`: the array can be its own hash table, and the answer is between 1 and `n + 1`.
2Keep this true: an index that holds its own value keeps it, and each swap sends one more value home.
3The shape: `for i in range(n):` with an inner loop that keeps moving the value at `i` to its home while it has one it does not fill yet; then a second loop over the indices, and a last return after it.
4The trap: test whether the home already holds the value, `nums[nums[i] - 1] != nums[i]`, not `nums[i] != i + 1`, or a repeated value swaps forever.

Target: First Missing Positive (LeetCode 41). `n` values fill at most the numbers 1 to `n`, so the answer is between 1 and `n + 1`, and only values from 1 to `n` need a home.

Boundary Model: Converging Boundaries [left, right] / Sliding Window [L, R]

Indices step monotonically inward or rightward. Each step permanently eliminates an entire row, column, or infeasible candidate window.

Loop Invariant Termination

while (left < right) for converging pointers; while (right < n) with inner window shrink.

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

A hash set would answer "is 1 here? is 2 here?" at once, but this problem allows no extra memory. Cyclic Sort makes the array its own set. A value v from 1 to n has a natural place, index v - 1: its home. Swap every such value into its home, and afterwards each index i either holds i + 1 (that number is present) or holds something else (that number is missing). The smallest missing positive is the first index that fails, plus one, or n + 1 when none fails: n values can fill at most the homes of 1 to n.

🧱 The Analogy: Numbered Lockers

Lockers numbered 1 to n stand in a row, and in front of each one waits a person with a ticket. If your ticket names a locker, you walk to it and swap places with whoever is there, unless that person already holds the same number. People with tickets like 0, -3 or 900 have no locker, so they stay wherever they are pushed. Once nobody can move, the first locker whose person holds a different number is the smallest number nobody had.

🪄 The Mathematical Harmony / Magic Trick
Code / Blueprint
for i in range(n):
while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
home = nums[i] - 1
nums[i], nums[home] = nums[home], nums[i]
 

Each swap puts one value into its home, and the while never moves a value that is home, so there are at most n swaps however the loops look. The test that ends the loop is about the home, not about i: when a repeated value finds its home already holding a copy, the swap would exchange two equal values and change nothing, and nums[nums[i] - 1] != nums[i] is what lets the loop stop.

💡 Summary

Swap each value v in 1..n to index v - 1 while its home does not hold it, then return the first i + 1 with nums[i] != i + 1, or n + 1. O(N)O(N)O(N) time (at most n swaps in all), O(1)O(1)O(1) extra space.

  • Testing the index instead of the home: loop while nums[nums[i] - 1] != nums[i], not while nums[i] != i + 1. With a repeated value, as in [1, 1], the home already holds a copy, the swap changes nothing, and the loop never ends.

  • The one-line swap: save home = nums[i] - 1 first. nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i] writes nums[i] before the second index is computed, so the value lands in the wrong place.

  • Values with no home: test 1 <= nums[i] <= n before reading nums[nums[i] - 1]. A 0 or a negative value gives a negative index, which Python reads from the end of the list without an error.

  • Testing the index instead of the value: the closing scan reads nums[i] != i + 1, not nums[i] != i. A filled home holds i + 1, the value that belongs there, not the bare index i, so comparing against i alone would call every filled home missing.

  • Forgetting n + 1: when every home holds its value, as in [2, 1], the answer is n + 1 = 3, which no index names.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

You will see how a senior engineer hears "smallest missing positive, O(1) extra memory" and uses the array as its own hash table.

Pattern Recognition Signals

The 10-second spot

"The smallest positive whole number (1, 2, 3, ...) that does not appear anywhere in nums", "O(n) time" and "only O(1) extra memory beyond the input array": a missing number, with no room for a hash set, and "changing the values inside nums is allowed". Only 1 to n + 1 can be the answer, and each of 1 to n names an index, so the signal is Cyclic Sort: index v - 1 is the home of v.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

An index j that holds j + 1 keeps it, and every swap sends one more value v from 1 to n to its home v - 1; when the swaps end, the first i with nums[i] != i + 1 gives the answer i + 1, or n + 1 if there is none.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • Loop on the home, nums[nums[i] - 1] != nums[i], not on nums[i] != i + 1: in [2,3,2,1] the 2 at index 0 finds its home, index 1, already holding a 2, and the index test would swap the two 2s forever.

  • Save home = nums[i] - 1 before swapping: nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i] writes nums[i] first, then computes the second index from the new value.

  • Check 1 <= nums[i] <= n before reading nums[nums[i] - 1]: a 0 or a negative value gives a negative index, which Python reads from the end of the list without an error, and a value above n is past the end.

  • Return n + 1 after the scan: when nums holds every number from 1 to n, as in [2,1], no index is missing its value and the answer is 3.

The 60-Second Interview Pitch

Say this out loud before you type a single line

I'd use Cyclic Sort and let the array be its own hash table. The answer has to be between 1 and n plus 1, because n values can cover at most the numbers 1 to n, so every other value can be ignored. Every value v from 1 to n has a home, index v minus 1. I walk the array, and while the current value has a home that doesn't hold it yet, I swap it there. Each swap sends one value home for good, so there are at most n swaps in total. Then I scan: the first index i whose value isn't i plus 1 gives the answer i plus 1, and if every home is filled it's n plus 1. The trap is the loop test: I check whether the home already holds v, not whether index i holds i plus 1, or a repeated value would swap forever. That's O(N) time and O(1) extra space.

So: the answer is in 1..n + 1, each v in 1..n has the home v - 1, swap until every value is home or has none, then scan.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

The outer for i in range(n) runs N times. The inner while looks slow, but each pass of its body is one swap that sends a value v to index v - 1, which holds v from then on, and an index that holds its own value is never swapped again: the while test fails there. So at most N swaps happen in the whole run, not per i, and the loops together make at most 2N tests of the while condition. The second for reads each index at most once and stops at the first gap: O(N). Total: O(N).

SPACE COMPLEXITY

O(1)

The swaps rearrange nums in place, and the code keeps only n, i and home: O(1) extra space, with no recursion. The answer is one integer.

Formal Recurrence Relation

T(N) = N (outer loop) + at most N swaps in all + N (scan) = O(N)

The outer for i in range(n) runs N times. The inner while looks slow, but each pass of its body is one swap that sends a value v to index v - 1, which holds v from then on, and an index that holds its own value is never swapped again: the while test fails there. So at most N swaps happen in the whole run, not per i, and the loops together make at most 2N tests of the while condition. The second for reads each index at most once and stops at the first gap: O(N). Total: O(N).

Derivation Progression

Outer loop

O(N)

for i in range(n) visits each index once; the while test runs once more than the swaps made at that i.

All swaps together

at most N

Each swap sends one value to its home v - 1 for good, and a value at home is never moved again, so the swaps across every i add up to at most N.

Scan

O(N)

The second for reads each index at most once and returns at the first i with nums[i] != i + 1.

Total

O(N)

O(N) loop steps, at most N swaps and one scan.

Variable Definitions

NNN

Number of values, len(nums) (at most 10^5)

Memory Architecture & Bounds

🟣 Call Stack

O(1): no recursion

🔵 Auxiliary Heap

O(1): n, i, home

🟢 Output Space

O(1): one integer

Boundary Best / Worst Cases

Best Case

O(N)O(N)O(N): no value has a home, as in [7,8,9,11,12], so no swap happens, but every index is still visited once

Average Case

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

Worst Case

O(N)O(N)O(N): a shuffled 1..N, where every value is swapped home once and the scan reads every index

Pointer Invariant Transition Progression

Pointer Invariant Transition Progression
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "the smallest positive whole number", **"does not appear anywhere in nums"**, "only O(1) extra memory beyond the input array". A missing number among 1 to n with no room for a set: Cyclic Sort, each value v sent to index v - 1.

CONSTRAINTS & BOUNDS

Up to 10510^5105 values from −231-2^{31}−231 to 231−12^{31} - 1231−1. A hash set of the values takes O(N)O(N)O(N) extra memory and sorting takes O(Nlog⁡N)O(N \log N)O(NlogN) time, both outside the stated bounds; Cyclic Sort makes at most 10510^5105 swaps in all, then one scan.

FAANG PRODUCTION TRAPS & EDGE CASES

The input array is the scratch space: a caller that still needs the original order must pass a copy, which brings back the O(N)O(N)O(N) memory the method avoids, so document the mutation. With values from −231-2^{31}−231 to 231−12^{31} - 1231−1, compute nums[i] - 1 only after checking 1 <= nums[i] <= n: in C or Java an unchecked index reads outside the array. The swaps jump to scattered positions, so on arrays much larger than the CPU cache each swap can be a cache miss, where a sequential scan is not.

Core Algorithmic State Invariants

1. Every Value Has a Home

A value `v` from 1 to `n` belongs at index `v - 1`. Zeros, negatives and values above `n` have no home and can stay anywhere, because the answer is between 1 and `n + 1`.

2. Check the Home, Not the Index

Swap while `nums[nums[i] - 1] != nums[i]`. With a repeated value the home already holds a copy, so testing `nums[i] != i + 1` would swap two equal values forever.

3. At Most N Swaps

Each swap sends one value home for good, so the `while` makes at most `n` swaps in the whole run: O(N) time, and the array itself is the table, O(1) extra space.

Theory Context•Two Pointers & Sliding Window
HardLC 41

First Missing Positive (LeetCode 41)

You will see how an array of n values can serve as its own hash table: each value from 1 to n is swapped to index v - 1.

Target Frequency:AmazonGoogleMicrosoftMeta

You get an array of integers, nums, in no particular order. It may hold zeros, negative numbers, very large numbers and repeated values. Find the smallest positive whole number (1, 2, 3, ...) that does not appear anywhere in nums, and return it.

Your solution must run in O(n) time, where n is the length of nums, and use only O(1) extra memory beyond the input array. Changing the values inside nums is allowed.

Worked Examples

Example 1
Input:nums = [1,2,0]
Output:3
1021020: no home
Explanation: 1 and 2 are both there, so the first positive number that is absent is 3. The 0 is not positive and plays no part.
Example 2
Input:nums = [3,4,-1,1]
Output:2
3041-12131 present
Explanation: 1 is present but 2 is not. The -1 is ignored, and 3 and 4 do not matter once 2 is missing.
Example 3
Input:nums = [7,8,9,11,12]
Output:1
708192113124
Explanation: No value is 1, so 1 itself is the answer; every value is larger than the length of the array.

⚖️Formal Constraints & Bounds

  • 1 <= nums.length <= 105

  • -231 <= nums[i] <= 231 - 1

Deep-Dive & Conceptual Insights

Why It Works & Core Invariant

A value v from 1 to n belongs at index v - 1, so the array can be its own hash table: send each such value home, and the first index that does not hold its own value names the smallest missing positive. Every other value can be ignored, because the answer is always between 1 and n + 1.

Real-World Scenario & Production Applications

Handing out the lowest free number: POSIX requires open() to return the lowest file descriptor that is not in use, and seat, locker or worker-slot numbers are often reused the same way. The numbers in use already say which slot each one fills, so the first empty slot is the answer.

Step-by-Step Execution Trace Table

Example 2, nums = [3,4,-1,1] (n = 4):

StepiValue nums[i]Home nums[i] - 1 holdsActionnums after
103-1swap: 3 goes home to index 2[-1,4,3,1]
20-1(no home)stop: -1 is not in 1..4[-1,4,3,1]
3141swap: 4 goes home to index 3[-1,1,3,4]
411-1swap: 1 goes home to index 0[1,-1,3,4]
51-1(no home)stop[1,-1,3,4]
6233stop: the home already holds 3[1,-1,3,4]
7344stop: the home already holds 4[1,-1,3,4]
8scannums[0] = 1; nums[1] = -1, not 2return 2
Scroll horizontally to see all columns, or expand to full screen

Three swaps for four values: each swap put one value in its home for good. With a repeated value, such as the second 2 in [2,3,2,1], the home already holds a copy; the test nums[nums[i] - 1] != nums[i] stops there, while nums[i] != i + 1 would swap the two 2s forever.

Core Invariant Specification & Code Shape
Archetype Code Shape
Python
1A value `v` from 1 to `n` has a home, index `v - 1`: the array can be its own hash table, and the answer is between 1 and `n + 1`.
2Keep this true: an index that holds its own value keeps it, and each swap sends one more value home.
3The shape: `for i in range(n):` with an inner loop that keeps moving the value at `i` to its home while it has one it does not fill yet; then a second loop over the indices, and a last return after it.
4The trap: test whether the home already holds the value, `nums[nums[i] - 1] != nums[i]`, not `nums[i] != i + 1`, or a repeated value swaps forever.

Target: First Missing Positive (LeetCode 41). `n` values fill at most the numbers 1 to `n`, so the answer is between 1 and `n + 1`, and only values from 1 to `n` need a home.

Boundary Model: Converging Boundaries [left, right] / Sliding Window [L, R]

Indices step monotonically inward or rightward. Each step permanently eliminates an entire row, column, or infeasible candidate window.

Loop Invariant Termination

while (left < right) for converging pointers; while (right < n) with inner window shrink.

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

A hash set would answer "is 1 here? is 2 here?" at once, but this problem allows no extra memory. Cyclic Sort makes the array its own set. A value v from 1 to n has a natural place, index v - 1: its home. Swap every such value into its home, and afterwards each index i either holds i + 1 (that number is present) or holds something else (that number is missing). The smallest missing positive is the first index that fails, plus one, or n + 1 when none fails: n values can fill at most the homes of 1 to n.

🧱 The Analogy: Numbered Lockers

Lockers numbered 1 to n stand in a row, and in front of each one waits a person with a ticket. If your ticket names a locker, you walk to it and swap places with whoever is there, unless that person already holds the same number. People with tickets like 0, -3 or 900 have no locker, so they stay wherever they are pushed. Once nobody can move, the first locker whose person holds a different number is the smallest number nobody had.

🪄 The Mathematical Harmony / Magic Trick
Code / Blueprint
for i in range(n):
while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
home = nums[i] - 1
nums[i], nums[home] = nums[home], nums[i]
 

Each swap puts one value into its home, and the while never moves a value that is home, so there are at most n swaps however the loops look. The test that ends the loop is about the home, not about i: when a repeated value finds its home already holding a copy, the swap would exchange two equal values and change nothing, and nums[nums[i] - 1] != nums[i] is what lets the loop stop.

💡 Summary

Swap each value v in 1..n to index v - 1 while its home does not hold it, then return the first i + 1 with nums[i] != i + 1, or n + 1. O(N)O(N)O(N) time (at most n swaps in all), O(1)O(1)O(1) extra space.

  • Testing the index instead of the home: loop while nums[nums[i] - 1] != nums[i], not while nums[i] != i + 1. With a repeated value, as in [1, 1], the home already holds a copy, the swap changes nothing, and the loop never ends.

  • The one-line swap: save home = nums[i] - 1 first. nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i] writes nums[i] before the second index is computed, so the value lands in the wrong place.

  • Values with no home: test 1 <= nums[i] <= n before reading nums[nums[i] - 1]. A 0 or a negative value gives a negative index, which Python reads from the end of the list without an error.

  • Testing the index instead of the value: the closing scan reads nums[i] != i + 1, not nums[i] != i. A filled home holds i + 1, the value that belongs there, not the bare index i, so comparing against i alone would call every filled home missing.

  • Forgetting n + 1: when every home holds its value, as in [2, 1], the answer is n + 1 = 3, which no index names.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

You will see how a senior engineer hears "smallest missing positive, O(1) extra memory" and uses the array as its own hash table.

Pattern Recognition Signals

The 10-second spot

"The smallest positive whole number (1, 2, 3, ...) that does not appear anywhere in nums", "O(n) time" and "only O(1) extra memory beyond the input array": a missing number, with no room for a hash set, and "changing the values inside nums is allowed". Only 1 to n + 1 can be the answer, and each of 1 to n names an index, so the signal is Cyclic Sort: index v - 1 is the home of v.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

An index j that holds j + 1 keeps it, and every swap sends one more value v from 1 to n to its home v - 1; when the swaps end, the first i with nums[i] != i + 1 gives the answer i + 1, or n + 1 if there is none.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • Loop on the home, nums[nums[i] - 1] != nums[i], not on nums[i] != i + 1: in [2,3,2,1] the 2 at index 0 finds its home, index 1, already holding a 2, and the index test would swap the two 2s forever.

  • Save home = nums[i] - 1 before swapping: nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i] writes nums[i] first, then computes the second index from the new value.

  • Check 1 <= nums[i] <= n before reading nums[nums[i] - 1]: a 0 or a negative value gives a negative index, which Python reads from the end of the list without an error, and a value above n is past the end.

  • Return n + 1 after the scan: when nums holds every number from 1 to n, as in [2,1], no index is missing its value and the answer is 3.

The 60-Second Interview Pitch

Say this out loud before you type a single line

I'd use Cyclic Sort and let the array be its own hash table. The answer has to be between 1 and n plus 1, because n values can cover at most the numbers 1 to n, so every other value can be ignored. Every value v from 1 to n has a home, index v minus 1. I walk the array, and while the current value has a home that doesn't hold it yet, I swap it there. Each swap sends one value home for good, so there are at most n swaps in total. Then I scan: the first index i whose value isn't i plus 1 gives the answer i plus 1, and if every home is filled it's n plus 1. The trap is the loop test: I check whether the home already holds v, not whether index i holds i plus 1, or a repeated value would swap forever. That's O(N) time and O(1) extra space.

So: the answer is in 1..n + 1, each v in 1..n has the home v - 1, swap until every value is home or has none, then scan.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

The outer for i in range(n) runs N times. The inner while looks slow, but each pass of its body is one swap that sends a value v to index v - 1, which holds v from then on, and an index that holds its own value is never swapped again: the while test fails there. So at most N swaps happen in the whole run, not per i, and the loops together make at most 2N tests of the while condition. The second for reads each index at most once and stops at the first gap: O(N). Total: O(N).

SPACE COMPLEXITY

O(1)

The swaps rearrange nums in place, and the code keeps only n, i and home: O(1) extra space, with no recursion. The answer is one integer.

Formal Recurrence Relation

T(N) = N (outer loop) + at most N swaps in all + N (scan) = O(N)

The outer for i in range(n) runs N times. The inner while looks slow, but each pass of its body is one swap that sends a value v to index v - 1, which holds v from then on, and an index that holds its own value is never swapped again: the while test fails there. So at most N swaps happen in the whole run, not per i, and the loops together make at most 2N tests of the while condition. The second for reads each index at most once and stops at the first gap: O(N). Total: O(N).

Derivation Progression

Outer loop

O(N)

for i in range(n) visits each index once; the while test runs once more than the swaps made at that i.

All swaps together

at most N

Each swap sends one value to its home v - 1 for good, and a value at home is never moved again, so the swaps across every i add up to at most N.

Scan

O(N)

The second for reads each index at most once and returns at the first i with nums[i] != i + 1.

Total

O(N)

O(N) loop steps, at most N swaps and one scan.

Variable Definitions

NNN

Number of values, len(nums) (at most 10^5)

Memory Architecture & Bounds

🟣 Call Stack

O(1): no recursion

🔵 Auxiliary Heap

O(1): n, i, home

🟢 Output Space

O(1): one integer

Boundary Best / Worst Cases

Best Case

O(N)O(N)O(N): no value has a home, as in [7,8,9,11,12], so no swap happens, but every index is still visited once

Average Case

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

Worst Case

O(N)O(N)O(N): a shuffled 1..N, where every value is swapped home once and the scan reads every index

Pointer Invariant Transition Progression

Pointer Invariant Transition Progression
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "the smallest positive whole number", **"does not appear anywhere in nums"**, "only O(1) extra memory beyond the input array". A missing number among 1 to n with no room for a set: Cyclic Sort, each value v sent to index v - 1.

CONSTRAINTS & BOUNDS

Up to 10510^5105 values from −231-2^{31}−231 to 231−12^{31} - 1231−1. A hash set of the values takes O(N)O(N)O(N) extra memory and sorting takes O(Nlog⁡N)O(N \log N)O(NlogN) time, both outside the stated bounds; Cyclic Sort makes at most 10510^5105 swaps in all, then one scan.

FAANG PRODUCTION TRAPS & EDGE CASES

The input array is the scratch space: a caller that still needs the original order must pass a copy, which brings back the O(N)O(N)O(N) memory the method avoids, so document the mutation. With values from −231-2^{31}−231 to 231−12^{31} - 1231−1, compute nums[i] - 1 only after checking 1 <= nums[i] <= n: in C or Java an unchecked index reads outside the array. The swaps jump to scattered positions, so on arrays much larger than the CPU cache each swap can be a cache miss, where a sequential scan is not.

Core Algorithmic State Invariants

1. Every Value Has a Home

A value `v` from 1 to `n` belongs at index `v - 1`. Zeros, negatives and values above `n` have no home and can stay anywhere, because the answer is between 1 and `n + 1`.

2. Check the Home, Not the Index

Swap while `nums[nums[i] - 1] != nums[i]`. With a repeated value the home already holds a copy, so testing `nums[i] != i + 1` would swap two equal values forever.

3. At Most N Swaps

Each swap sends one value home for good, so the `while` makes at most `n` swaps in the whole run: O(N) time, and the array itself is the table, O(1) extra space.

Rosetta Dual-Monaco Comparison
Python 3
CANONICAL INVARIANT TEMPLATE
Loading...
CONCRETE: FIRST MISSING POSITIVE (LEETCODE 41)
T = O(N)S = O(1)
Loading...
Pattern Implementation Mapping TableCanonical Invariant ⟷ Concrete Code ⟷ Engineering Rationale
Canonical InvariantConcrete CodeEngineering Rationale
The answer lies between 1 and n + 1n = len(nums)`n` values fill at most the numbers 1 to `n`, so the answer is between 1 and `n + 1`, and only values from 1 to `n` need a home.
Send the value home while it has one it does not fill yet (the trap: test the home)while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:The range test comes first so `nums[i] - 1` is a real index; the home test stops at a repeated value, whose home already holds a copy.
Fix the home index before the swaphome = nums[i] - 1The swap changes `nums[i]`; saving the home first keeps both targets of the swap pointing at the right places.
One swap: one value home for goodnums[i], nums[home] = nums[home], nums[i]`v` lands at `v - 1` and is never moved again; the value that was there comes to `i` and is tested next.
The first index without its value is the answerif nums[i] != i + 1: return i + 1Every value from 1 to `n` that is present sits at its home, so the first index that fails names the smallest missing number.
Every home filledreturn n + 1All of 1 to `n` are present, so the next number, `n + 1`, is the smallest one missing.
© 2026 Hi👋WebEnterprise. All rights reserved.
Sitemap•llms.txt•