Stage 1 · Code
Dynamic Programming & Greedy
DP Drills
From 1D recurrence to 2D tables, string alignment, and state machines — drill the DP patterns that appear most in interviews.
The DP Mindset
Dynamic programming is recursion + memoisation turned inside out. The hard part is never the code — it's identifying the state variables. Ask: what decisions lead from one subproblem to the next? The answer defines your DP table dimensions.
Write a recursive solution first. Then add memoisation. Then (optionally) convert to bottom-up tabulation. This progression works for every DP problem — never try to write the bottom-up table directly on the first attempt.
DP Patterns
| Pattern | State (i = index) | Recurrence |
|---|---|---|
| 1D DP (Fibonacci-style) | dp[i] = best up to i | dp[i] = f(dp[i-1], dp[i-2]) |
| House Robber (take/skip) | dp[i] = max gain up to i | dp[i] = max(dp[i-1], nums[i] + dp[i-2]) |
| 0/1 Knapsack | dp[i][w] = max value with first i items, weight ≤ w | dp[i][w] = max(dp[i-1][w], val[i] + dp[i-1][w-wt[i]]) |
| String DP (LCS, Edit Dist) | dp[i][j] = best up to s1[:i], s2[:j] | Match → 1+dp[i-1][j-1]; else max/min of adjacent |
| State Machine (Buy/Sell Stock) | dp[i][k][holding] | dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1]+price) |
| Unbounded (Coin Change) | dp[a] = min coins to make amount a | dp[a] = min(dp[a], 1 + dp[a - coin]) |
Problems
Key Points
- Start recursive, add memo, then bottom-up — the only reliable DP workflow.
- 1D DP is usually a scan with 2–3 previous values — space optimisation to O(1) is often possible.
- 2D DP tables for strings — LCS, edit distance, longest palindrome all build a matrix of prefixes.
- State machines for buy/sell stock — holding/not-holding/cooldown are finite states, not indices.
- Knapsack variant: 0/1 vs unbounded — 0/1 iterates items outer loop; unbounded iterates amount outer loop.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.