Dynamic Programming — Introduction & Thinking
📖 Concept
Dynamic Programming (DP) solves problems by breaking them into overlapping sub-problems and storing results to avoid recomputation. It's the single most important topic for coding interviews.
When to use DP:
- Optimal substructure — optimal solution is built from optimal sub-solutions
- Overlapping sub-problems — same sub-problems are solved multiple times
DP vs other techniques:
- D&C — sub-problems are INDEPENDENT (no overlap) → merge sort
- Greedy — make local optimal choice, no backtracking → activity selection
- DP — sub-problems OVERLAP, need to consider ALL options → knapsack
Two approaches:
- Top-Down (Memoization) — Start from the big problem, recurse down, cache results
- Bottom-Up (Tabulation) — Start from smallest sub-problems, build up to the answer
The DP thinking process:
- Define the state — What does dp[i] represent?
- Find the recurrence — How does dp[i] relate to smaller states?
- Identify the base case — What are the smallest sub-problems?
- Determine the order — Which states must be computed first?
- Compute the answer — Where in the table is the final answer?
Common DP patterns:
- Linear DP: dp[i] depends on dp[i-1], dp[i-2], ...
- Grid DP: dp[i][j] depends on dp[i-1][j], dp[i][j-1], ...
- Interval DP: dp[i][j] = optimal over range [i, j]
- Knapsack: dp[i][w] = best using first i items with capacity w
🏠 Real-world analogy: DP is like writing an exam booklet. If question 5 asks "what was the answer to question 3?", you don't re-solve question 3 — you look back at your already-written answer.
💻 Code Example
1// FIBONACCI — The gateway to DP23// Naive recursion: O(2ⁿ) time — TERRIBLE4function fibNaive(n) {5 if (n <= 1) return n;6 return fibNaive(n - 1) + fibNaive(n - 2);7}89// Top-Down (Memoization): O(n) time, O(n) space10function fibMemo(n, memo = {}) {11 if (n <= 1) return n;12 if (memo[n]) return memo[n];13 memo[n] = fibMemo(n - 1, memo) + fibMemo(n - 2, memo);14 return memo[n];15}1617// Bottom-Up (Tabulation): O(n) time, O(n) space18function fibTab(n: number): number {19 if (n <= 1) return n;20 const dp = new Array(n + 1);21 dp[0] = 0; dp[1] = 1;22 for (let i = 2; i <= n; i++) {23 dp[i] = dp[i - 1] + dp[i - 2];24 }25 return dp[n];26}2728// Space-Optimized: O(n) time, O(1) space29function fibOptimal(n: number): number {30 if (n <= 1) return n;31 let prev = 0, curr = 1;32 for (let i = 2; i <= n; i++) {33 [prev, curr] = [curr, prev + curr];34 }35 return curr;36}3738// CLIMBING STAIRS — Easy DP39function climbStairs(n: number): number {40 if (n <= 2) return n;41 let prev = 1, curr = 2;42 for (let i = 3; i <= n; i++) {43 [prev, curr] = [curr, prev + curr];44 }45 return curr;46}47// dp[i] = dp[i-1] + dp[i-2] — same as fibonacci!4849// MINIMUM COST CLIMBING STAIRS50function minCostClimbing(cost: number[]): number {51 const n = cost.length;52 const dp = new Array(n + 1).fill(0);53 for (let i = 2; i <= n; i++) {54 dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);55 }56 return dp[n];57}
🏋️ Practice Exercise
Practice Problems (Easy → Hard):
- Fibonacci with memoization and tabulation
- Climbing stairs — ways to reach step n (1 or 2 steps at a time)
- Min cost climbing stairs
- House robber — max money without robbing adjacent houses
- Maximum subarray (Kadane's algorithm as DP)
- Decode ways — count decodings of a digit string
- Longest increasing subsequence
- Coin change — minimum coins to make amount
- Word break — can string be segmented into dictionary words?
- Longest common subsequence of two strings
⚠️ Common Mistakes
Not identifying overlapping sub-problems — if sub-problems are independent, use D&C instead
Forgetting the base case — every DP needs properly initialized base cases
Wrong state definition — if dp[i] doesn't clearly represent something, the recurrence will be wrong
Not optimizing space — many 1D DP problems only need the last 1-2 values, not the full array
Jumping to DP without trying simpler approaches first — greedy or brute force may be sufficient
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Dynamic Programming — Introduction & Thinking