๐ง Dynamic Programming
One-line summary: Break a problem into overlapping subproblems, solve each once โ turning exponential time into polynomial.
Diagramโ
๐ฏ Conceptโ
Dynamic Programming (DP) solves complex problems by breaking them into simpler subproblems, solving each subproblem once, and storing (caching) the result. Apply DP when a problem has both:
- Optimal substructure: the optimal solution is built from optimal solutions of its subproblems.
- Overlapping subproblems: the same subproblem is computed many times by a naive recursion.
flowchart TD
A["Naive recursion\nexponential, recomputes"] --> B{"Overlapping\nsubproblems?"}
B -->|Yes| C["Add caching"]
C --> D["Top-Down\n(Memoization)\nrecursion + cache"]
C --> E["Bottom-Up\n(Tabulation)\niterative table"]
D --> F["Polynomial time"]
E --> F
Top-Down vs Bottom-Upโ
| Aspect | Top-Down (Memoization) | Bottom-Up (Tabulation) |
|---|---|---|
| Style | Recursion + cache | Iterative table filling |
| Order | Solves on demand | Solves all states in order |
| Space | O(states) + call stack | O(states), often space-optimizable |
| Intuition | Easier to write from recurrence | Faster, no recursion overhead |
Common DP Categoriesโ
1D DP ยท 2D / grid DP ยท Knapsack (take / not-take) ยท LIS ยท LCS / DP on strings ยท DP on stocks ยท Partition / interval DP ยท Bitmask DP.
โก Time & Space Complexityโ
| Pattern | Time | Space |
|---|---|---|
| 1D DP (house robber, climb stairs) | O(n) | O(1) optimised |
| 2D DP (grid / string) | O(mยทn) | O(n) row-optimised |
| 0/1 Knapsack | O(nยทW) | O(W) |
| LIS (DP) | O(nยฒ) | O(n) |
| LIS (patience/binary search) | O(n log n) | O(n) |
| LCS | O(mยทn) | O(mยทn) |
Key Insight: The number of distinct states ร work per state = total time. Optimize space by keeping only the states you still need (e.g., last row/two variables).
Common Patternsโ
1D DP โ House Robberโ
function rob(nums) {
let prev2 = 0,
prev1 = 0;
for (const n of nums) {
const curr = Math.max(prev1, prev2 + n);
prev2 = prev1;
prev1 = curr;
}
return prev1;
}
// State: best loot up to house i. Time O(n), Space O(1).
2D DP โ Edit Distance (Levenshtein)โ
function editDistance(w1, w2) {
const m = w1.length,
n = w2.length;
const dp = Array.from({ length: m + 1 }, (_, i) =>
Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),
);
for (let i = 1; i <= m; i++)
for (let j = 1; j <= n; j++)
dp[i][j] =
w1[i - 1] === w2[j - 1]
? dp[i - 1][j - 1]
: 1 + Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]);
return dp[m][n];
}
// Time O(m*n), Space O(m*n).
0/1 Knapsack โ take / not-takeโ
function knapsack(weights, values, W) {
const dp = new Array(W + 1).fill(0);
for (let i = 0; i < weights.length; i++)
for (let w = W; w >= weights[i]; w--)
// iterate backwards for 0/1
dp[w] = Math.max(dp[w], dp[w - weights[i]] + values[i]);
return dp[W];
}
// Time O(n*W), Space O(W).
LIS โ Longest Increasing Subsequence O(n log n)โ
function lengthOfLIS(nums) {
const tails = [];
for (const x of nums) {
let lo = 0,
hi = tails.length;
while (lo < hi) {
const mid = (lo + hi) >> 1;
if (tails[mid] < x) lo = mid + 1;
else hi = mid;
}
tails[lo] = x;
}
return tails.length;
}
// Binary search keeps the smallest tail per length. Time O(n log n).
๐งช Worked Example: Coin Change (min coins)โ
Given coin denominations and an amount, find the fewest coins to make it.
function coinChange(coins, amount) {
const dp = new Array(amount + 1).fill(Infinity);
dp[0] = 0; // 0 coins to make amount 0
for (let a = 1; a <= amount; a++) {
for (const coin of coins) {
if (coin <= a) dp[a] = Math.min(dp[a], dp[a - coin] + 1);
}
}
return dp[amount] === Infinity ? -1 : dp[amount];
}
// dp[a] = fewest coins to form amount a. Time O(amount * coins), Space O(amount).
Recurrence: dp[a] = min(dp[a - coin] + 1) over all coins that fit โ optimal substructure (best for a uses the best for a - coin) and overlapping subproblems (dp[a - coin] reused).
Pitfallsโ
- Wrong iteration order: 0/1 knapsack must iterate capacity backwards; unbounded knapsack forwards.
- Uninitialized base cases: forgetting
dp[0]leads to wrong answers. - Not space-optimizing: many 2D DPs only need the previous row.
- Confusing subsequence vs substring: contiguity changes the recurrence.
Practice Problemsโ
| Problem | Difficulty | Solution |
|---|---|---|
| LC 70 โ Climbing Stairs | Easy | |
| LC 121 โ Best Time to Buy and Sell Stock | Easy | |
| LC 198 โ House Robber | Medium | |
| LC 322 โ Coin Change | Medium | |
| LC 300 โ Longest Increasing Subsequence | Medium | |
| LC 1143 โ Longest Common Subsequence | Medium |
| LC 62 โ Unique Paths | Medium | | | LC 63 โ Unique Paths II | Medium | | | LC 64 โ Minimum Path Sum | Medium | | | LC 91 โ Decode Ways | Medium | | | LC 96 โ Unique Binary Search Trees | Medium | | | LC 120 โ Triangle | Medium | | | LC 139 โ Word Break | Medium | | | LC 152 โ Maximum Product Subarray | Medium | | | LC 213 โ House Robber II | Medium | | | LC 221 โ Maximal Square | Medium | | | LC 279 โ Perfect Squares | Medium | | | LC 300 โ Longest Increasing Subsequence | Medium | | | LC 309 โ Best Time to Buy and Sell Stock with Cooldown | Medium | | | LC 322 โ Coin Change | Medium | | | LC 338 โ Counting Bits | Medium | | | LC 343 โ Integer Break | Medium | | | LC 377 โ Combination Sum IV | Medium | | | LC 416 โ Partition Equal Subset Sum | Medium | | | LC 494 โ Target Sum | Medium | | | LC 516 โ Longest Palindromic Subsequence | Medium | | | LC 518 โ Coin Change 2 | Medium | |
| LC 740 โ Delete and Earn | Medium | | | LC 931 โ Minimum Falling Path Sum | Medium | |
| LC 42 โ Trapping Rain Water | Hard | | | LC 44 โ Wildcard Matching | Hard | | | LC 72 โ Edit Distance | Hard | | | LC 85 โ Maximal Rectangle | Hard | | | LC 87 โ Scramble String | Hard | | | LC 115 โ Distinct Subsequences | Hard | | | LC 123 โ Best Time to Buy and Sell Stock III | Hard | | | LC 132 โ Palindrome Partitioning II | Hard | | | LC 140 โ Word Break II | Hard | | | LC 188 โ Best Time to Buy and Sell Stock IV | Hard | | | LC 312 โ Burst Balloons | Hard | | | LC 329 โ Longest Increasing Path in a Matrix | Hard | | | LC 354 โ Russian Doll Envelopes | Hard | | | LC 410 โ Split Array Largest Sum | Hard | | | LC 446 โ Arithmetic Slices II - Subsequence | Hard | | | LC 472 โ Concatenated Words | Hard | | | LC 546 โ Remove Boxes | Hard | | | LC 664 โ Strange Printer | Hard | | | LC 689 โ Maximum Sum of 3 Non-Overlapping Subarrays | Hard | | | LC 1000 โ Minimum Cost to Merge Stones | Hard | | | LC 1092 โ Shortest Common Supersequence | Hard | | | LC 1235 โ Maximum Profit in Job Scheduling | Hard | | | CC โ LCS (LCSSTR) | Hard | | | CC โ Advanced DP (ADVDP) | Hard | | | CC โ Matrix Chain Multiplication (MATCHAIN) | Hard | |
Related Topicsโ
- Recursion โ memoisation is recursion + cache
- Kadane's Algorithm โ 1D DP solved greedily
- Backtracking โ DP prunes redundant states; backtracking explores all
โ Back to Home ยท ยฉ sparshjaswal