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•Intervals & Greedy
MediumLC 55

Jump Game (LeetCode 55)

Target Frequency:AmazonGoogleMicrosoft

You get an integer array nums and begin on index 0. The value nums[i] is the longest jump you may make from index i: from there you can move forward by any whole number of steps from 1 up to nums[i], and a value of 0 means you cannot move on from that index.

Return true if some sequence of jumps lands you on the last index, and false if every sequence gets stuck before it.

Worked Examples

Example 1
Input:nums = [2,3,1,1,4]
Output:true
2031121344startjump 1jump 2
Explanation: Index 1 is one step away, and its value 3 carries you straight to index 4, the last index. Other routes work too; one is enough.
Example 2
Input:nums = [3,2,1,0,4]
Output:false
3021120344stuckout of reach
Explanation: Indices 0, 1 and 2 can each get as far as index 3 and no further (0 + 3, 1 + 2, 2 + 1), and index 3 holds 0, so no jump ever passes it. Index 4 stays out of reach.

⚖️Formal Constraints & Bounds

  • 1 <= nums.length <= 104

  • 0 <= nums[i] <= 105

Deep-Dive & Conceptual Insights

Core Insight

You never need the path, only how far any path can get: the reachable indices always form one block 0..reach, so one number and one pass decide the answer.

Real-World Scenario & Production Applications

Any chain of forward hops with a limited range per hop: relay stations along a pipeline, charging stops for a drone, stepping stones on a path. Whether the end can be reached never needs the full route, only the furthest point any route could reach so far, so one running number answers it in a single pass.

Step-by-Step Execution Trace Table

Example 2, nums = [3,2,1,0,4] (the trap case):

inums[i]Check i > reachreach = max(reach, i + nums[i])What it means
030 > 0: nomax(0, 0 + 3) = 3Indices 0 to 3 can be landed on
121 > 3: nomax(3, 1 + 2) = 3No further than before
212 > 3: nomax(3, 2 + 1) = 3No further than before
303 > 3: nomax(3, 3 + 0) = 3Index 3 can't move on
444 > 3: yes(not reached)No jump lands on index 4: return False
Code Shape
Archetype Code Shape
Python
1You never need the path, only how far any path can get: keep `reach`, the furthest index a run of jumps can land on so far.
2Every index from `0` to `reach` can be landed on (a jump may be shorter than `nums[i]`), so extend it with `reach = max(reach, i + nums[i])`: the larger reach keeps every option.
3Start `reach = 0`, loop `for i in range(len(nums))` once, and `return True` after the loop.
4The trap: check `if i > reach: return False` before reading `nums[i]`, or an index nobody can land on extends `reach`.

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

A path search looks necessary here: from index 0 you could jump 1, 2, ... up to nums[0] steps, and every landing spot branches again. Greedy skips the search. A jump may be shorter than its maximum, so if some jump can land on index k, every index before k can be landed on too. The reachable indices are therefore always one unbroken block 0..reach, and a single number, reach, says everything about the past. Walk the array once, and at each index you can stand on, push reach out to i + nums[i] if that is further.

🪜 The Analogy: Stepping Stones Across a River

You cross a river on a row of stepping stones. Each stone has a number painted on it: how many stones ahead you can leap from there, at most. You don't plan a route. You walk along the stones you can reach and keep one note in your head: "the furthest stone I could get to so far." Each new stone may move that note further. If you ever look at a stone beyond the note, nobody can stand on it, and the far bank is out of reach.

🔑 Why It Works

This is the greedy argument in one line: max keeps the larger block, and a larger block contains every index a smaller one does, so choosing it can never cost an option. A locally best choice that never has to be undone is exactly when greedy is correct. The order of the two lines matters: check i > reach first, so an index nobody can land on never extends reach.

  • Extending reach from an index you can't stand on: check i > reach before reach = max(reach, i + nums[i]). On [3,2,1,0,4] index 4 is past reach = 3; letting its jump count returns True instead of False.

  • Assigning instead of taking the max: reach = i + nums[i] lets a short jump after a long one shrink the reach, so [4,1,0,0,0] gets stuck at index 3 and returns False instead of True.

  • Searching paths: trying every jump length from every index is correct but costs up to O(N · max(nums[i])), about 10^9 steps at these limits. One number, reach, replaces the whole search.

  • Answering a different question: reach only says yes or no. The fewest jumps, as in Jump Game II (LC 45), needs a second boundary for where the current jump runs out.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

"The longest jump from each index" and "can you reach the last index": a yes/no reachability question where a longer jump is never worse than a shorter one. When the locally best option (the furthest reach) keeps every choice any other option keeps, that is the signal for Greedy.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Decision rule at each index i: if i > reach, return False; otherwise reach = max(reach, i + nums[i]).

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

This problem's traps are in Common Pitfalls above.

The 60-Second Interview Pitch

Say this out loud before you type a single line

I'd solve this with Greedy. I never need the actual path, only the furthest index any sequence of jumps could land on so far; I call it reach. A jump can be shorter than its maximum, so every index up to reach can be landed on, and the reachable indices always form one block from zero to reach. I walk the array once. At each index I first check whether i is past reach: if it is, nobody can stand there, so I return false. Otherwise I extend reach to the max of reach and i plus nums of i. Taking the max never loses an option, because a longer block contains every shorter one. The trap is the order: checking first stops an unreachable index from pushing reach forward. If the loop finishes, I return true. One pass, so O(N) time and O(1) space.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

Look at the code: reach = 0 is one assignment, and for i in range(len(nums)) visits each index at most once. Its body does one comparison (i > reach) and one max, a constant amount of work, and the loop may stop early at return False. Total: O(N).

SPACE COMPLEXITY

O(1)

The code keeps only reach and i, whatever the input size, and returns one boolean: O(1) extra space.

Formal Recurrence Relation

T(N) = O(1) + N · O(1) = O(N)

Derivation Progression

Start

O(1)

reach = 0 is one assignment.

Index loop

at most N iterations

for i in range(len(nums)) visits each index once, and stops early if return False runs.

Per-index work

O(1) per iteration

One comparison i > reach and one max(reach, i + nums[i]), whatever N is.

Total

O(N)

Constant work per index over at most N indices.

Variable Definitions

NNN

Number of indices, len(nums)

reachreachreach

Furthest index some run of jumps can land on so far

Memory Architecture & Bounds

🟣 Call Stack

O(1) Iterative, no recursion

🔵 Auxiliary Heap

O(1): reach, i

🟢 Output Space

O(1): one boolean

Boundary Best / Worst Cases

Best Case

O(1)O(1)O(1): nums[0] = 0 with more than one index, so the loop returns False at i = 1

Average Case

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

Worst Case

O(N)O(N)O(N): the last index is reachable, so every index is checked

Recurrence Tree Topology

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

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "the longest jump allowed from each index", "can you reach the last index". A yes/no reachability question where a longer jump is never worse than a shorter one: Greedy with one running number, reach.

CONSTRAINTS & BOUNDS

N≤104N \le 10^4N≤104 indices and jumps up to 10510^5105. Trying every jump length from every index costs up to N⋅max⁡(nums[i])≈109N \cdot \max(nums[i]) \approx 10^9N⋅max(nums[i])≈109 steps; the greedy reach is O(N)O(N)O(N) time and O(1)O(1)O(1) space, and it reads nums once, left to right, so it also works on a stream.

FAANG PRODUCTION TRAPS & EDGE CASES

On a stream, a record that arrives beyond the covered prefix must wait: it can't move the prefix forward until the gap before it is filled. i + nums[i] is at most 104+10510^4 + 10^5104+105, so it fits a 32-bit integer with room to spare.

Core Algorithmic State Invariants

  1. Why "At Most" Makes One Number Enough

If every jump had to be exactly nums[i] long, the reachable indices could have holes, and one number could not describe them: you would need a set of indices or a table. Because a jump may be shorter, the reachable indices have no holes, and reach alone says everything.

  1. True After the Loop Needs No Extra Test

The loop only finishes when no index failed i > reach, the last index included, so return True needs no check such as reach >= len(nums) - 1.

  1. A Zero Is a Wall Only If Nothing Jumps Over It

nums[i] == 0 stops the walk only when reach == i at that moment. Any earlier index that jumps past it keeps reach beyond it, as in [2,0,0], where index 0 already reaches the last index.

Theory Context•Intervals & Greedy
MediumLC 55

Jump Game (LeetCode 55)

Target Frequency:AmazonGoogleMicrosoft

You get an integer array nums and begin on index 0. The value nums[i] is the longest jump you may make from index i: from there you can move forward by any whole number of steps from 1 up to nums[i], and a value of 0 means you cannot move on from that index.

Return true if some sequence of jumps lands you on the last index, and false if every sequence gets stuck before it.

Worked Examples

Example 1
Input:nums = [2,3,1,1,4]
Output:true
2031121344startjump 1jump 2
Explanation: Index 1 is one step away, and its value 3 carries you straight to index 4, the last index. Other routes work too; one is enough.
Example 2
Input:nums = [3,2,1,0,4]
Output:false
3021120344stuckout of reach
Explanation: Indices 0, 1 and 2 can each get as far as index 3 and no further (0 + 3, 1 + 2, 2 + 1), and index 3 holds 0, so no jump ever passes it. Index 4 stays out of reach.

⚖️Formal Constraints & Bounds

  • 1 <= nums.length <= 104

  • 0 <= nums[i] <= 105

Deep-Dive & Conceptual Insights

Core Insight

You never need the path, only how far any path can get: the reachable indices always form one block 0..reach, so one number and one pass decide the answer.

Real-World Scenario & Production Applications

Any chain of forward hops with a limited range per hop: relay stations along a pipeline, charging stops for a drone, stepping stones on a path. Whether the end can be reached never needs the full route, only the furthest point any route could reach so far, so one running number answers it in a single pass.

Step-by-Step Execution Trace Table

Example 2, nums = [3,2,1,0,4] (the trap case):

inums[i]Check i > reachreach = max(reach, i + nums[i])What it means
030 > 0: nomax(0, 0 + 3) = 3Indices 0 to 3 can be landed on
121 > 3: nomax(3, 1 + 2) = 3No further than before
212 > 3: nomax(3, 2 + 1) = 3No further than before
303 > 3: nomax(3, 3 + 0) = 3Index 3 can't move on
444 > 3: yes(not reached)No jump lands on index 4: return False
Code Shape
Archetype Code Shape
Python
1You never need the path, only how far any path can get: keep `reach`, the furthest index a run of jumps can land on so far.
2Every index from `0` to `reach` can be landed on (a jump may be shorter than `nums[i]`), so extend it with `reach = max(reach, i + nums[i])`: the larger reach keeps every option.
3Start `reach = 0`, loop `for i in range(len(nums))` once, and `return True` after the loop.
4The trap: check `if i > reach: return False` before reading `nums[i]`, or an index nobody can land on extends `reach`.

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

A path search looks necessary here: from index 0 you could jump 1, 2, ... up to nums[0] steps, and every landing spot branches again. Greedy skips the search. A jump may be shorter than its maximum, so if some jump can land on index k, every index before k can be landed on too. The reachable indices are therefore always one unbroken block 0..reach, and a single number, reach, says everything about the past. Walk the array once, and at each index you can stand on, push reach out to i + nums[i] if that is further.

🪜 The Analogy: Stepping Stones Across a River

You cross a river on a row of stepping stones. Each stone has a number painted on it: how many stones ahead you can leap from there, at most. You don't plan a route. You walk along the stones you can reach and keep one note in your head: "the furthest stone I could get to so far." Each new stone may move that note further. If you ever look at a stone beyond the note, nobody can stand on it, and the far bank is out of reach.

🔑 Why It Works

This is the greedy argument in one line: max keeps the larger block, and a larger block contains every index a smaller one does, so choosing it can never cost an option. A locally best choice that never has to be undone is exactly when greedy is correct. The order of the two lines matters: check i > reach first, so an index nobody can land on never extends reach.

  • Extending reach from an index you can't stand on: check i > reach before reach = max(reach, i + nums[i]). On [3,2,1,0,4] index 4 is past reach = 3; letting its jump count returns True instead of False.

  • Assigning instead of taking the max: reach = i + nums[i] lets a short jump after a long one shrink the reach, so [4,1,0,0,0] gets stuck at index 3 and returns False instead of True.

  • Searching paths: trying every jump length from every index is correct but costs up to O(N · max(nums[i])), about 10^9 steps at these limits. One number, reach, replaces the whole search.

  • Answering a different question: reach only says yes or no. The fewest jumps, as in Jump Game II (LC 45), needs a second boundary for where the current jump runs out.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

"The longest jump from each index" and "can you reach the last index": a yes/no reachability question where a longer jump is never worse than a shorter one. When the locally best option (the furthest reach) keeps every choice any other option keeps, that is the signal for Greedy.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Decision rule at each index i: if i > reach, return False; otherwise reach = max(reach, i + nums[i]).

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

This problem's traps are in Common Pitfalls above.

The 60-Second Interview Pitch

Say this out loud before you type a single line

I'd solve this with Greedy. I never need the actual path, only the furthest index any sequence of jumps could land on so far; I call it reach. A jump can be shorter than its maximum, so every index up to reach can be landed on, and the reachable indices always form one block from zero to reach. I walk the array once. At each index I first check whether i is past reach: if it is, nobody can stand there, so I return false. Otherwise I extend reach to the max of reach and i plus nums of i. Taking the max never loses an option, because a longer block contains every shorter one. The trap is the order: checking first stops an unreachable index from pushing reach forward. If the loop finishes, I return true. One pass, so O(N) time and O(1) space.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N)

Look at the code: reach = 0 is one assignment, and for i in range(len(nums)) visits each index at most once. Its body does one comparison (i > reach) and one max, a constant amount of work, and the loop may stop early at return False. Total: O(N).

SPACE COMPLEXITY

O(1)

The code keeps only reach and i, whatever the input size, and returns one boolean: O(1) extra space.

Formal Recurrence Relation

T(N) = O(1) + N · O(1) = O(N)

Derivation Progression

Start

O(1)

reach = 0 is one assignment.

Index loop

at most N iterations

for i in range(len(nums)) visits each index once, and stops early if return False runs.

Per-index work

O(1) per iteration

One comparison i > reach and one max(reach, i + nums[i]), whatever N is.

Total

O(N)

Constant work per index over at most N indices.

Variable Definitions

NNN

Number of indices, len(nums)

reachreachreach

Furthest index some run of jumps can land on so far

Memory Architecture & Bounds

🟣 Call Stack

O(1) Iterative, no recursion

🔵 Auxiliary Heap

O(1): reach, i

🟢 Output Space

O(1): one boolean

Boundary Best / Worst Cases

Best Case

O(1)O(1)O(1): nums[0] = 0 with more than one index, so the loop returns False at i = 1

Average Case

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

Worst Case

O(N)O(N)O(N): the last index is reachable, so every index is checked

Recurrence Tree Topology

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

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "the longest jump allowed from each index", "can you reach the last index". A yes/no reachability question where a longer jump is never worse than a shorter one: Greedy with one running number, reach.

CONSTRAINTS & BOUNDS

N≤104N \le 10^4N≤104 indices and jumps up to 10510^5105. Trying every jump length from every index costs up to N⋅max⁡(nums[i])≈109N \cdot \max(nums[i]) \approx 10^9N⋅max(nums[i])≈109 steps; the greedy reach is O(N)O(N)O(N) time and O(1)O(1)O(1) space, and it reads nums once, left to right, so it also works on a stream.

FAANG PRODUCTION TRAPS & EDGE CASES

On a stream, a record that arrives beyond the covered prefix must wait: it can't move the prefix forward until the gap before it is filled. i + nums[i] is at most 104+10510^4 + 10^5104+105, so it fits a 32-bit integer with room to spare.

Core Algorithmic State Invariants

  1. Why "At Most" Makes One Number Enough

If every jump had to be exactly nums[i] long, the reachable indices could have holes, and one number could not describe them: you would need a set of indices or a table. Because a jump may be shorter, the reachable indices have no holes, and reach alone says everything.

  1. True After the Loop Needs No Extra Test

The loop only finishes when no index failed i > reach, the last index included, so return True needs no check such as reach >= len(nums) - 1.

  1. A Zero Is a Wall Only If Nothing Jumps Over It

nums[i] == 0 stops the walk only when reach == i at that moment. Any earlier index that jumps past it keeps reach beyond it, as in [2,0,0], where index 0 already reaches the last index.

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