The goal isn't to finish 69 problems. It's to leave with a reduction table in your head, you read a statement, spot the signal, and the pattern falls out. Everything here is built to install that.
Tap the circle beside a problem to cycle status: ○ to do → ● fresh → ◐ assisted → ✦ revised. Progress saves to this browser automatically.
Time-box 30 minutes for Easy/Medium, 45 for Hard. Timer visible. When it ends, read the editorial only until you have the idea, then close it and derive the rest. Never copy code, then mark the problem assisted.
| # | Step | What you actually write |
|---|---|---|
| 1 | Restate | The problem in your words, 2 sentences. If you can't, you haven't read it. |
| 2 | Constraints | n range, value range, sorted?, distinct?, negatives?, in-place? The numbers are the biggest hint in the problem. |
| 3 | Brute force | The dumbest correct solution + its complexity. Always, even when obvious. |
| 4 | The waste | One sentence: what work is the brute force repeating? This sentence is the whole problem. |
| 5 | Invariant | The property you maintain as a pointer/window moves. Can't state it → you'll write buggy code. |
| 6 | Algorithm in prose | Numbered steps, no syntax. Include what happens at the boundaries. |
| 7 | Dry run | Smallest example + one adversarial (empty, all-same, all-negative, k=1, k=n). Track variables in a table. |
| 8 | Code | Only now. |
| 9 | Trigger card | "When I see ___, reach for ___, because ___." This is the artifact. Everything else is scaffolding. |
| Signal in the statement | Reach for | Why |
|---|---|---|
| Sorted + find a pair/triple with a target | Converging two pointers | Sortedness makes each move monotone, you discard a whole side. |
| Contiguous subarray, longest/shortest with a constraint | Variable-size window | The constraint is monotone in window size. |
| Contiguous, exactly length k | Fixed window | Add one, drop one, O(1) transition. |
| Count subarrays with sum exactly k | Prefix sum + hashmap | sum(i..j)=P[j]−P[i−1] → a pair-counting problem. |
| Count subarrays with at most k | atMost(k) window | Windows ending at r give r−l+1 per step. |
| Count with exactly k | atMost(k) − atMost(k−1) | The standard trick, learn it once, it's everywhere. |
| Many range updates, one final read | Difference array | O(1) per update, one pass to materialize. |
| In-place, O(1) space, keep relative order | Write pointer | Read and write can be decoupled. |
| Values are in range 1..n | Index-as-hash / cyclic sort | The array is a hashmap. |
| Max/min over every window | Monotonic deque | Discard elements that can never win. |
| Running best ending here | Kadane / running-extreme | Reframe "best overall" as "best ending at i". |
| Intervals, two sorted lists | Two pointers on intervals | Advance whichever ends first. |
f(subarray) satisfies P" → "Find/count pairs of prefix indices (i, j) where
g(P[j], P[i]) satisfies P"Almost every "count subarrays with..." problem is this move plus a hashmap. Sum, sum-mod-k, count-of-odds, balanced 0s-and-1s, all the same skeleton with a different quantity being prefixed.
Re-solve from the trigger card only, not the code, on day +3, +10, +30. Success = you rebuilt the algorithm in prose within 10 minutes, not that you recalled the code. Anything that fails twice goes back to Phase 0 of its own pattern.
Daily: 2 problems (1 new + 1 revision) on weekdays, 3–4 new on weekends. Every problem gets a written entry, no exceptions. The writing is the method.
Weekly: one 90-minute session re-deriving a Phase-7-level problem cold, on paper, talking out loud. The only part that simulates an interview.
Phase gates: don't advance until the exit check passes. If Phase 5 takes 10 days instead of 7, take 10 days, the phases are dependencies, not a schedule.
What "done" looks like: you can hand someone the reduction table you built yourself, and it's longer and more precise than the one above.
## [number]. [title] — [difficulty] — [date] — [fresh | assisted | revision] Restated: Constraints that matter: Brute force + complexity: The waste: Invariant: Algorithm (prose): Dry run: Edge cases hit: Complexity: time __ / space __ TRIGGER: when I see ___ , reach for ___ , because ___ Mistake I made: Revisit: +3 __ / +10 __ / +30 __