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•Backtracking & State Search
MediumLC 139

Word Break (LeetCode 139)

Target Frequency:AmazonMetaGoogle

Given a string s and a dictionary wordDict of allowed words, decide whether s can be broken up into a run of one or more dictionary words placed back to back with nothing left over.

A dictionary word is free to appear more than once across the breakdown.

Worked Examples

Example 1
Input:s = "leetcode", wordDict = ["leet","code"]
Output:true
Explanation: Splitting "leetcode" into "leet" + "code" uses only dictionary words, so the answer is true.
Example 2
Input:s = "applepenapple", wordDict = ["apple","pen"]
Output:true
Explanation: "applepenapple" breaks into "apple" + "pen" + "apple", reusing the dictionary word "apple" twice, so the answer is true.
Example 3
Input:s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
Output:false
Explanation: Splitting as cats + and or cat + sand leaves og, which is not a word, so no split works.

⚖️Formal Constraints & Bounds

  • 1 <= s.length <= 300

  • 1 <= wordDict.length <= 1000

  • 1 <= wordDict[i].length <= 20

  • s and wordDict[i] consist of only lowercase English letters.

  • All the strings of wordDict are unique.

Deep-Dive & Conceptual Insights

Core Insight

A boolean memo table caches suffix viability, collapsing duplicate recursive subtrees.

Real-World Scenario & Production Applications

Natural language tokenization, URL path segmentation without spaces.

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Reachability State Definition

dp[i] is True if the prefix s[:i] can be fully segmented into dictionary words. dp[0] = True -- the empty prefix needs zero words.

Mathematical Recurrence / Code Invariant
dp = [False] * (len(s) + 1)
dp[0] = True

Step-by-Step Execution Trace Table

Code / Blueprint
"leetcode" (Root, d=0, remaining="leetcode")
|
choose "leet"| (startswith("leet") == True)
v
"code" (d=1, remaining="code", memo check: Miss)
|
choose "code"| (startswith("code") == True)
v
"" (d=2, remaining="", Base Case Hit!)
✅ Return True
|
Memoize memo["code"] = True <-- Bubble Up
Memoize memo["leetcode"] = True <-- Bubble Up
 
Step-by-Step Decision Trace
  1. Step 1 (Root, d=0, remaining="leetcode"): Evaluate dictionary choices:
    • "code": Does "leetcode" start with "code"? →\rightarrow→ No (Skip).
    • "leet": Does "leetcode" start with "leet"? →\rightarrow→ Yes!
  2. Step 2 (Choose "leet", d=1, remaining="code"): Chop off "leet" →\rightarrow→ call dfs("code").
  3. Step 3 (Suffix "code", d=1): memo check: not yet cached. Evaluate dictionary choices:
    • "leet": Does "code" start with "leet"? →\rightarrow→ No (Skip).
    • "code": Does "code" start with "code"? →\rightarrow→ Yes!
  4. Step 4 (Choose "code", d=2, remaining=""): Chop off "code" →\rightarrow→ call dfs("").
  5. Step 5 (Base Case, d=2): remaining == "" →\rightarrow→ Record Match: Return True ✅.
  6. Step 6 (Memoize & Bubble Up, d=0):
    • Cache memo["code"] = True →\rightarrow→ Return True.
    • Cache memo["leetcode"] = True →\rightarrow→ Record Final Result: True ✅.
Full Walkthrough6 Steps
Input:s = "leetcode", wordDict = ["leet","code"]Expected:true
1🌱 ROOT(Root, d=0, remaining="leetcode")
Evaluate dictionary choices:
  • "code": Does "leetcode" start with "code"? →\rightarrow→ No (Skip).
  • "leet": Does "leetcode" start with "leet"? →\rightarrow→ Yes!
2🟢 CHOOSE(Choose "leet", d=1, remaining="code")
Chop off "leet" →\rightarrow→ call dfs("code").
3⚡ STEP(Suffix "code", d=1)
memo check: not yet cached. Evaluate dictionary choices:
  • "leet": Does "code" start with "leet"? →\rightarrow→ No (Skip).
  • "code": Does "code" start with "code"? →\rightarrow→ Yes!
4🟢 CHOOSE(Choose "code", d=2, remaining="")
Chop off "code" →\rightarrow→ call dfs("").
5✅ RECORD / GOAL(Base Case, d=2)
remaining == "" →\rightarrow→ Record Match: Return True ✅.
6🌱 ROOT(Memoize & Bubble Up, d=0)
  • Cache memo["code"] = True →\rightarrow→ Return True.
  • Cache memo["leetcode"] = True →\rightarrow→ Record Final Result: True ✅.
Code Shape
Archetype Code Shape
Python
1word_set = set(wordDict)
2memo = {}
3def dfs(start):
4 if start == len(s):
5 return True
6 if start in memo:
7 return memo[start]
8 for end in range(start + 1, len(s) + 1):
9 if s[start:end] in word_set and dfs(end):
10 memo[start] = True
11 return True
12 memo[start] = False
13 return False
14return dfs(0)

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

Plain backtracking re-derives an answer from scratch every time it visits the same state — and for a string like "aaaaaaa", the same remaining suffix gets explored through wildly different paths, over and over, causing an exponential blowup.

🗺️ The Analogy: A Hiker Who Writes Notes on Dead-End Trail Markers

Imagine a hiker exploring a trail network, trying to reach the exit. Every time they hit a dead end at a specific junction, they pin a note there: "dead end, don't bother trying from here again." The next time any path — even one arriving from a totally different direction — leads back to that same junction, the hiker reads the note and immediately turns around, instead of re-exploring every trail branching off from it all over again.

🔑 The Key Idea in the Code

The key insight is that "can I successfully break the string starting from index start?" only depends on start itself — not on how the recursion arrived there — so the very first time it's computed, the answer can be cached and reused by every future arrival at that same index.

  • Missing failed-suffix cache: Re-evaluating suffix substrings that were already proven impossible causes O(2N)O(2^N)O(2N) TLE. Caching memo[start] = False prevents redundant exponential path exploration.

  • Linear list lookup on wordDict: Checking s[start:end] in wordDict on a Python list takes O(W⋅L)O(W \cdot L)O(W⋅L) time per prefix. Converting wordDict to a set guarantees O(1)O(1)O(1) average lookups.

  • Over-slicing string bounds: Attempting to slice beyond len(s) or not defining the base case start == len(s) -> return True.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

String segmentation against a dictionary with overlapping prefix choices.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Invariant: memo[start] records whether suffix s[start:] can be segmented into words.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • Forgetting memoization: repeatedly testing failing suffixes leads to exponential 2^N time.

The 60-Second Interview Pitch

Say this out loud before you type a single line

"I use top-down DFS with a memo dictionary. From index start, I loop end from start + 1 to len(s) + 1. If s[start:end] is in word_set and dfs(end) returns True, I memoize and return True. If all cuts fail, I memoize False. Each start runs once, tries up to N ends, and each slice costs up to N, so it runs in O(N^3) time and O(N) space."

Interview Tip: There are two valid ways to structure the recursion: 1) Index-Based Range Scanning (for end in range(start + 1, len(s) + 1): with set lookup), or 2) Word-Choice Suffix Matching (for word in wordDict: with remaining.startswith(word) and suffix memoization). Both achieve top-down memoized optimality.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N^3 + W · L)

Look at the execution steps: Let N = len(s), W = len(wordDict), L = max word length. Building word_set takes O(W · L). memo lets each of the N start indices run its loop once. That loop tries every end from start + 1 to N, and slicing and hashing s[start:end] costs up to N: O(N^2) per start, O(N^3) in all. Capping end at start + L would make it O(N · L^2).

SPACE COMPLEXITY

O(N + W · L) Auxiliary

Memoization array of size N + 1, recursion stack of depth N, and word set of size W · L.

Formal Recurrence Relation

T(N) = O(W · L) + ∑_{i=1}^N ∑_{j=i+1}^N O(j - i) = O(N^3 + W · L)

Derivation Progression

Word Set Preprocessing

O(W · L) hash set

Hashes every dictionary word once.

State Space

N suffix start indices

memo[start] records whether s[start:] is segmentable, so each start runs its loop once.

Substring Slicing & Verification

for end ∈ [start+1, N]: s[start:end] ∈ word_set

Up to N slices per start, each O(end - start) to build and hash: O(N^2) per start.

Variable Definitions

NNN

Length of the target string s

WWW

Number of words in dictionary

LLL

Maximum length of any dictionary word

Memory Architecture & Bounds

🟣 Call Stack

O(N) Recursion stack depth

🔵 Auxiliary Heap

O(N + W · L) Memoization cache and word set

🟢 Output Space

O(1) Boolean return

Boundary Best / Worst Cases

Best Case

O(N)O(N)O(N) when every one-letter prefix is a word, as in s = "aaaa", wordDict = ["a"]: each call cuts after one letter and succeeds.

Worst Case

O(N3)O(N^3)O(N3) when no segmentation exists and every start tries every end.

Decision & State-Space Search Tree

Decision & State-Space Search Tree
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "segment string into dictionary words". Suffix memoization: cache whether s[start:]s[start:]s[start:] can be successfully partitioned.

CONSTRAINTS & BOUNDS

s.length≤300s.length \le 300s.length≤300. Memoization guarantees at most NNN distinct subproblems.

Theory Context•Backtracking & State Search
MediumLC 139

Word Break (LeetCode 139)

Target Frequency:AmazonMetaGoogle

Given a string s and a dictionary wordDict of allowed words, decide whether s can be broken up into a run of one or more dictionary words placed back to back with nothing left over.

A dictionary word is free to appear more than once across the breakdown.

Worked Examples

Example 1
Input:s = "leetcode", wordDict = ["leet","code"]
Output:true
Explanation: Splitting "leetcode" into "leet" + "code" uses only dictionary words, so the answer is true.
Example 2
Input:s = "applepenapple", wordDict = ["apple","pen"]
Output:true
Explanation: "applepenapple" breaks into "apple" + "pen" + "apple", reusing the dictionary word "apple" twice, so the answer is true.
Example 3
Input:s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
Output:false
Explanation: Splitting as cats + and or cat + sand leaves og, which is not a word, so no split works.

⚖️Formal Constraints & Bounds

  • 1 <= s.length <= 300

  • 1 <= wordDict.length <= 1000

  • 1 <= wordDict[i].length <= 20

  • s and wordDict[i] consist of only lowercase English letters.

  • All the strings of wordDict are unique.

Deep-Dive & Conceptual Insights

Core Insight

A boolean memo table caches suffix viability, collapsing duplicate recursive subtrees.

Real-World Scenario & Production Applications

Natural language tokenization, URL path segmentation without spaces.

Subproblems & Recurrence Decomposition3 Phases

🧩Subproblem 1: Reachability State Definition

dp[i] is True if the prefix s[:i] can be fully segmented into dictionary words. dp[0] = True -- the empty prefix needs zero words.

Mathematical Recurrence / Code Invariant
dp = [False] * (len(s) + 1)
dp[0] = True

Step-by-Step Execution Trace Table

Code / Blueprint
"leetcode" (Root, d=0, remaining="leetcode")
|
choose "leet"| (startswith("leet") == True)
v
"code" (d=1, remaining="code", memo check: Miss)
|
choose "code"| (startswith("code") == True)
v
"" (d=2, remaining="", Base Case Hit!)
✅ Return True
|
Memoize memo["code"] = True <-- Bubble Up
Memoize memo["leetcode"] = True <-- Bubble Up
 
Step-by-Step Decision Trace
  1. Step 1 (Root, d=0, remaining="leetcode"): Evaluate dictionary choices:
    • "code": Does "leetcode" start with "code"? →\rightarrow→ No (Skip).
    • "leet": Does "leetcode" start with "leet"? →\rightarrow→ Yes!
  2. Step 2 (Choose "leet", d=1, remaining="code"): Chop off "leet" →\rightarrow→ call dfs("code").
  3. Step 3 (Suffix "code", d=1): memo check: not yet cached. Evaluate dictionary choices:
    • "leet": Does "code" start with "leet"? →\rightarrow→ No (Skip).
    • "code": Does "code" start with "code"? →\rightarrow→ Yes!
  4. Step 4 (Choose "code", d=2, remaining=""): Chop off "code" →\rightarrow→ call dfs("").
  5. Step 5 (Base Case, d=2): remaining == "" →\rightarrow→ Record Match: Return True ✅.
  6. Step 6 (Memoize & Bubble Up, d=0):
    • Cache memo["code"] = True →\rightarrow→ Return True.
    • Cache memo["leetcode"] = True →\rightarrow→ Record Final Result: True ✅.
Full Walkthrough6 Steps
Input:s = "leetcode", wordDict = ["leet","code"]Expected:true
1🌱 ROOT(Root, d=0, remaining="leetcode")
Evaluate dictionary choices:
  • "code": Does "leetcode" start with "code"? →\rightarrow→ No (Skip).
  • "leet": Does "leetcode" start with "leet"? →\rightarrow→ Yes!
2🟢 CHOOSE(Choose "leet", d=1, remaining="code")
Chop off "leet" →\rightarrow→ call dfs("code").
3⚡ STEP(Suffix "code", d=1)
memo check: not yet cached. Evaluate dictionary choices:
  • "leet": Does "code" start with "leet"? →\rightarrow→ No (Skip).
  • "code": Does "code" start with "code"? →\rightarrow→ Yes!
4🟢 CHOOSE(Choose "code", d=2, remaining="")
Chop off "code" →\rightarrow→ call dfs("").
5✅ RECORD / GOAL(Base Case, d=2)
remaining == "" →\rightarrow→ Record Match: Return True ✅.
6🌱 ROOT(Memoize & Bubble Up, d=0)
  • Cache memo["code"] = True →\rightarrow→ Return True.
  • Cache memo["leetcode"] = True →\rightarrow→ Record Final Result: True ✅.
Code Shape
Archetype Code Shape
Python
1word_set = set(wordDict)
2memo = {}
3def dfs(start):
4 if start == len(s):
5 return True
6 if start in memo:
7 return memo[start]
8 for end in range(start + 1, len(s) + 1):
9 if s[start:end] in word_set and dfs(end):
10 memo[start] = True
11 return True
12 memo[start] = False
13 return False
14return dfs(0)

Conceptual Narrative

🧭 Conceptual Foundation & Pattern Intuition

Plain backtracking re-derives an answer from scratch every time it visits the same state — and for a string like "aaaaaaa", the same remaining suffix gets explored through wildly different paths, over and over, causing an exponential blowup.

🗺️ The Analogy: A Hiker Who Writes Notes on Dead-End Trail Markers

Imagine a hiker exploring a trail network, trying to reach the exit. Every time they hit a dead end at a specific junction, they pin a note there: "dead end, don't bother trying from here again." The next time any path — even one arriving from a totally different direction — leads back to that same junction, the hiker reads the note and immediately turns around, instead of re-exploring every trail branching off from it all over again.

🔑 The Key Idea in the Code

The key insight is that "can I successfully break the string starting from index start?" only depends on start itself — not on how the recursion arrived there — so the very first time it's computed, the answer can be cached and reused by every future arrival at that same index.

  • Missing failed-suffix cache: Re-evaluating suffix substrings that were already proven impossible causes O(2N)O(2^N)O(2N) TLE. Caching memo[start] = False prevents redundant exponential path exploration.

  • Linear list lookup on wordDict: Checking s[start:end] in wordDict on a Python list takes O(W⋅L)O(W \cdot L)O(W⋅L) time per prefix. Converting wordDict to a set guarantees O(1)O(1)O(1) average lookups.

  • Over-slicing string bounds: Attempting to slice beyond len(s) or not defining the base case start == len(s) -> return True.

Senior SWE Reasoning Architecture

4-Phase Thought Process Model

Pattern Recognition Signals

The 10-second spot

String segmentation against a dictionary with overlapping prefix choices.

Formulating the Predicate & Invariants

Turning intuition into a boolean rule

Invariant: memo[start] records whether suffix s[start:] can be segmented into words.

Silent Failure Traps & Edge Cases

Where confident candidates still lose points

  • Forgetting memoization: repeatedly testing failing suffixes leads to exponential 2^N time.

The 60-Second Interview Pitch

Say this out loud before you type a single line

"I use top-down DFS with a memo dictionary. From index start, I loop end from start + 1 to len(s) + 1. If s[start:end] is in word_set and dfs(end) returns True, I memoize and return True. If all cuts fail, I memoize False. Each start runs once, tries up to N ends, and each slice costs up to N, so it runs in O(N^3) time and O(N) space."

Interview Tip: There are two valid ways to structure the recursion: 1) Index-Based Range Scanning (for end in range(start + 1, len(s) + 1): with set lookup), or 2) Word-Choice Suffix Matching (for word in wordDict: with remaining.startswith(word) and suffix memoization). Both achieve top-down memoized optimality.

Big-O Invariant Derivation

Complexity & Mathematical Proof

TIME COMPLEXITY

O(N^3 + W · L)

Look at the execution steps: Let N = len(s), W = len(wordDict), L = max word length. Building word_set takes O(W · L). memo lets each of the N start indices run its loop once. That loop tries every end from start + 1 to N, and slicing and hashing s[start:end] costs up to N: O(N^2) per start, O(N^3) in all. Capping end at start + L would make it O(N · L^2).

SPACE COMPLEXITY

O(N + W · L) Auxiliary

Memoization array of size N + 1, recursion stack of depth N, and word set of size W · L.

Formal Recurrence Relation

T(N) = O(W · L) + ∑_{i=1}^N ∑_{j=i+1}^N O(j - i) = O(N^3 + W · L)

Derivation Progression

Word Set Preprocessing

O(W · L) hash set

Hashes every dictionary word once.

State Space

N suffix start indices

memo[start] records whether s[start:] is segmentable, so each start runs its loop once.

Substring Slicing & Verification

for end ∈ [start+1, N]: s[start:end] ∈ word_set

Up to N slices per start, each O(end - start) to build and hash: O(N^2) per start.

Variable Definitions

NNN

Length of the target string s

WWW

Number of words in dictionary

LLL

Maximum length of any dictionary word

Memory Architecture & Bounds

🟣 Call Stack

O(N) Recursion stack depth

🔵 Auxiliary Heap

O(N + W · L) Memoization cache and word set

🟢 Output Space

O(1) Boolean return

Boundary Best / Worst Cases

Best Case

O(N)O(N)O(N) when every one-letter prefix is a word, as in s = "aaaa", wordDict = ["a"]: each call cuts after one letter and succeeds.

Worst Case

O(N3)O(N^3)O(N3) when no segmentation exists and every start tries every end.

Decision & State-Space Search Tree

Decision & State-Space Search Tree
Synthesizing vector architecture diagram...
Staff+ Engineering Perspective

Senior SWE Deconstruction & Hardware Caveats

ARCHITECTURAL SIGNALS & INTERVIEW TRIGGERS

Triggers: "segment string into dictionary words". Suffix memoization: cache whether s[start:]s[start:]s[start:] can be successfully partitioned.

CONSTRAINTS & BOUNDS

s.length≤300s.length \le 300s.length≤300. Memoization guarantees at most NNN distinct subproblems.

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