Pattern #64
Dynamic Programming
Master overlapping subproblems and optimal substructure. Solve once, memoize results, transition between states, and optimize space from bottom-up tables.
Must Solve
25 core questions โ solve these first.
- 1.Climbing Stairs1D DP: ways[i] = ways[i-1] + ways[i-2]easy
- 2.House RobberTake vs Skip: max(dp[i-1], nums[i] + dp[i-2])medium
- 3.House Robber IICircular array: rob 0..n-2 or 1..n-1medium
- 4.Coin ChangeUnbounded Knapsack min coins: min(dp[w], 1 + dp[w-coin])medium
- 5.Coin Change IIUnbounded combinations: dp[w] += dp[w-coin]medium
- 6.Maximum Product SubarrayTrack both maxProduct and minProduct due to negative flipsmedium
- 7.Longest Increasing Subsequencedp[i] = max(dp[j] + 1) for j < i or O(n log n) patience sortmedium
- 8.Longest Common Subsequence2D String DP: match -> 1 + dp[i-1][j-1], else max(top, left)medium
- 9.Word BreakPartition DP: dp[i] = true if dp[j] && wordDict.contains(s[j:i])medium
- 10.Decode Ways1D string DP: 1 digit valid + 2 digit valid (10..26)medium
- 11.Unique PathsGrid DP: dp[r][c] = dp[r-1][c] + dp[r][c-1]medium
- 12.Minimum Path SumGrid DP: dp[r][c] = grid[r][c] + min(dp[r-1][c], dp[r][c-1])medium
- 13.Partition Equal Subset Sum0/1 Knapsack: find subset sum target = sum/2medium
- 14.Target Sum0/1 Knapsack subset sum transformation: P = (sum + target) / 2medium
- 15.0/1 KnapsackTake vs Skip: iterate capacity right-to-left in 1D arraymedium
- 16.Edit Distance2D String DP: insert, delete, or replace operationsmedium
- 17.Palindromic SubstringsExpand around center or 2D substring DP dp[i][j]medium
- 18.Longest Palindromic SubsequenceSubsequence DP: match -> 2 + dp[i+1][j-1], else max(dp[i+1][j], dp[i][j-1])medium
- 19.Best Time to Buy and Sell Stock with CooldownState Machine DP: states = (hold, sold, reset)medium
- 20.Best Time to Buy and Sell Stock IIIState Machine DP: 2 transactions limit, 4 variableshard
- 21.Dungeon GameReverse Grid DP: compute min health required from bottom-right to top-lefthard
- 22.Interleaving String2D String DP: dp[i][j] checks prefix matches of s1 and s2 with s3medium
- 23.Distinct SubsequencesString DP counting: match -> dp[i-1][j-1] + dp[i-1][j]hard
- 24.Burst BalloonsInterval / Matrix Chain DP: last balloon burst k in range (i, j)hard
- 25.House Robber IIITree DP: postorder DFS returns (robCurrent, skipCurrent)medium
Also Important
15 essential DP variations worth practicing.
- 26.Fibonacci NumberBase DP: dp[i] = dp[i-1] + dp[i-2] with O(1) spaceeasy
- 27.Min Cost Climbing Stairs1D DP: dp[i] = cost[i] + min(dp[i-1], dp[i-2])easy
- 28.Combination Sum IVUnbounded Knapsack permutations: loop capacity first, then itemsmedium
- 29.Perfect SquaresUnbounded Knapsack min items: dp[i] = min(dp[i], 1 + dp[i - s*s])medium
- 30.TriangleGrid DP: bottom-up accumulation dp[i][j] += min(dp[i+1][j], dp[i+1][j+1])medium
- 31.Maximal Square2D Grid DP: dp[r][c] = 1 + min(top, left, diagonal) for 1smedium
- 32.Longest Palindromic SubstringSubstring DP or expand around center in O(n^2)medium
- 33.Regular Expression Matching2D String Matching with . and * wildcardshard
- 34.Wildcard Matching2D String Matching with ? and * wildcardshard
- 35.Minimum Falling Path SumGrid DP: dp[r][c] = cell + min(left, center, right)medium
- 36.Cherry PickupGrid DP with 2 simultaneous paths: dp[r1][c1][r2]hard
- 37.Stone GameInterval Game DP: max difference dp[i][j] = max(piles[i]-dp[i+1][j], piles[j]-dp[i][j-1])medium
- 38.Delete and EarnTransform frequency sum to House Robber patternmedium
- 39.Integer BreakMath / DP: max product dp[i] = max(j * (i-j), j * dp[i-j])medium
- 40.Maximum Length of Repeated Subarray2D Continuous Subarray DP: match -> 1 + dp[i+1][j+1]medium
How to Think
Before writing DP code, answer the 4 questions: State definition, Cell Meaning, Transitions, and Base Cases.
- Same smaller problem repeating?Dynamic Programming
- Can I describe the problem with a state?dp[state] = answer
- Does current answer depend on previous states?Transition
- Recursive solution repeats work?Memoization (Top-Down)
- Can I compute states in dependency order?Tabulation (Bottom-Up)
- Take current item or skip current item?Take / Skip Pattern
- Two strings comparison or alignment?dp[i][j]
- Grid reachability or minimum cost path?dp[r][c]
Go Quick Reference โ Dynamic Programming
Compilable Go implementations showing Top-Down Memoization and Space-Optimized Bottom-Up Tabulation.
package main
import "fmt"
// Top-Down Memoization with int64 overflow protection
func coinChangeMemo(coins []int, amount int, memo map[int]int64) int64 {
if amount == 0 {
return 0
}
if amount < 0 {
return -1
}
if val, exists := memo[amount]; exists {
return val
}
var minCoins int64 = 1e18 // Use large int64 sentinel to prevent overflow
for _, coin := range coins {
res := coinChangeMemo(coins, amount-coin, memo)
if res >= 0 && res+1 < minCoins {
minCoins = res + 1
}
}
if minCoins == 1e18 {
memo[amount] = -1
} else {
memo[amount] = minCoins
}
return memo[amount]
}
// Bottom-Up Tabulation with Space Optimization O(1) space
func robTabulation(nums []int) int {
if len(nums) == 0 {
return 0
}
var prev2, prev1 int = 0, 0
for _, num := range nums {
// Core invariant: current best = max(skip current, rob current + best 2 houses back)
take := num + prev2
skip := prev1
current := take
if skip > take {
current = skip
}
prev2 = prev1
prev1 = current
}
return prev1
}
func main() {
memo := make(map[int]int64)
fmt.Println("Min Coins:", coinChangeMemo([]int{1, 2, 5}, 11, memo)) // 3
fmt.Println("Max Robbed:", robTabulation([]int{2, 7, 9, 3, 1})) // 12
}๐ Top-Down & Bottom-Up: O(N ร Transitions) time and O(N) or O(1) space.
Core DP Patterns & Mechanics
The 4 Golden Questions
1. State: What parameters uniquely identify a subproblem?
2. Meaning: What exactly does dp[state] represent?
3. Transition: How is current state computed from smaller solved states?
4. Base Case: What are the known trivial boundaries?
Take / Skip Decision Framework
At item i, evaluate:
โข Skip: Inherit answer from dp[i-1].
โข Take: Combine item value with dp[i-1][rem_capacity] or dp[i-2].
Choose max() or min() depending on goal.
Repeated subproblems โ Store & reuse state
Take / Skip decision โ dp[i] = opt(dp[i-1], val + dp[i-2])
0/1 Knapsack 1D table โ Iterate capacity right to left
Unbounded Knapsack 1D โ Iterate capacity left to right
2D String Matching โ dp[i][j] diagonal match or top/left max
Time Complexity โ Number of States ร Work per StateDP Families & Variants
1D & Grid DP
โข 1D DP: State depends on single index dp[i] (Climbing Stairs, House Robber, LIS).
โข Grid DP: State represents cell dp[r][c] moving down or right (Unique Paths, Min Path Sum).
2D String & Knapsack DP
โข String DP: dp[i][j] compares prefix of string A with prefix of string B (LCS, Edit Distance).
โข Knapsack: dp[w] tracks maximum value for capacity w (0/1 vs Unbounded).
0/1 vs Unbounded Knapsack Loop Direction
In 1D space-optimized Knapsack tables:
โข 0/1 Knapsack (each item used once): Loop capacity right to left (w = W down to weight) to read unchanged values from previous item pass.
โข Unbounded Knapsack (items reused freely): Loop capacity left to right (w = weight up to W) so newly updated values can be immediately reused.
Common Interview Mistakes
- โข Coding before clearly defining what dp[state] means in plain language.
- โข Leaving necessary constraint variables out of the state definition (e.g. remaining capacity, holding stock, or transaction count).
- โข Using the wrong loop direction in 1D Knapsack (updating left-to-right in 0/1 Knapsack accidentally reuses items multiple times).
- โข Incorrect base cases or failing to initialize unreachable states to infinity or negative infinity.
- โข Integer overflow when counting total combinations or paths (forgetting int64 guards or modulo arithmetic).
- โข Optimizing space to O(1) or O(N) prematurely before getting the full multi-dimensional DP table logic correct.
- โข Confusing continuous subarrays (contiguous elements) with non-continuous subsequences (can skip elements).
Interview Rules
Repeated Subproblems โ Dynamic Programming
Step 1 โ Define dp[state] meaning explicitly
Step 2 โ Identify decision choices (Take vs Skip)
Step 3 โ Formulate transition equation
Step 4 โ Set boundary base cases
0/1 Knapsack 1D โ Right-to-Left capacity loop
Unbounded 1D โ Left-to-Right capacity loop
2D String Matching โ Matrix dp[i][j]
Time Complexity โ Total States ร Work per State
Space Optimization โ Optimize array dimensions after correctness๐ก Golden Rule: Define exactly what one DP state means, then express that state using smaller already-solved states.
Production Thinking
Resource & Pricing Optimization โ matching cloud servers or inventory to budget constraints uses 0/1 or Unbounded Knapsack DP states.
Sequence Alignment & Diff Tools โ git diffs, document comparison, and DNA sequence matching rely on LCS and Edit Distance 2D DP matrices.
Workflow & State Scheduling โ state machine DP optimizes multi-stage system pipelines with cooling periods and transaction limits.
Production warning โ DP table size scales with input values (pseudopolynomial time); huge capacities require continuous approximations, branch-and-bound, or greedy heuristics.
Remember This
Identify repeating subproblems
Define dp[state] cell meaning
Formulate state transition formula
Establish correct base cases
Top-Down (Memoization) or Bottom-Up (Tabulation)
Check loop direction for 1D Knapsack tables
Verify bounds and avoid integer overflow