DSA & CS / 7. DYNAMIC PROGRAMMING
Dynamic Programming
Overlapping subproblems + optimal substructure — memoize everything
EXPLANATION
Dynamic Programming solves problems by breaking them into overlapping subproblems, solving each once, and storing the result. Two approaches: • Top-down (Memoization) → recursion + cache. Natural to write, start here • Bottom-up (Tabulation) → fill a table iteratively. No recursion overhead, often faster DP applies when: 1. Optimal substructure → optimal solution contains optimal solutions to subproblems 2. Overlapping subproblems → same subproblems solved multiple times The DP thinking process: 1. Define dp[i] or dp[i][j] — what does it represent? 2. Find the recurrence relation → how does dp[i] depend on previous states? 3. Set base cases 4. Determine traversal order (which dp values need to be computed first?) Common DP patterns: • 1D DP: fibonacci, climbing stairs, house robber • 2D DP: grid paths, edit distance, LCS • Knapsack: subset sum, coin change, 0/1 knapsack • Interval DP: matrix chain, burst balloons
DIAGRAM
Fibonacci (naive vs DP):
Naive: fib(5) = fib(4) + fib(3)
fib(3) computed TWICE → O(2^n)
Memoization: cache fib(3) after first compute → O(n)
memo = {0:0, 1:1}
Coin Change (bottom-up):
coins=[1,3,4], amount=6
dp[0]=0
dp[1]=1 (one 1-coin)
dp[2]=2 (two 1-coins)
dp[3]=1 (one 3-coin)
dp[4]=1 (one 4-coin)
dp[5]=2 (4+1)
dp[6]=2 (3+3) ← answerCODE