Lesson 7.1: Memoization

Memoization is a top-down approach to solving dynamic programming problems. It stores the results of expensive function calls and reuses them when the same inputs occur again.

๐Ÿ“Œ Key Points

๐Ÿงช Examples

# Fibonacci with memoization memo = {} def fib(n): if n in memo: return memo[n] if n <= 1: return n memo[n] = fib(n-1) + fib(n-2) return memo[n]
# Climbing Stairs memo = {} def climb(n): if n <= 2: return n if n in memo: return memo[n] memo[n] = climb(n-1) + climb(n-2) return memo[n]

Lesson 7.2: Tabulation

Tabulation is the bottom-up method of solving dynamic programming problems. It solves all related subproblems first and builds up the final answer.

๐Ÿ“Œ Key Points

๐Ÿงช Examples

# Fibonacci with tabulation def fib(n): dp = [0] * (n+1) dp[1] = 1 for i in range(2, n+1): dp[i] = dp[i-1] + dp[i-2] return dp[n]
# Climbing Stairs def climb(n): dp = [0] * (n+1) dp[1], dp[2] = 1, 2 for i in range(3, n+1): dp[i] = dp[i-1] + dp[i-2] return dp[n]

Lesson 7.3: Classic DP Problems

Dynamic programming shines in solving classic optimization and counting problems. These include subsequence problems, grid paths, knapsack, and more.

๐Ÿ“Œ Key Points

๐Ÿงช Examples

# Longest Common Subsequence def lcs(s1, s2): m, n = len(s1), len(s2) dp = [[0]*(n+1) for _ in range(m+1)] for i in range(1, m+1): for j in range(1, n+1): if s1[i-1] == s2[j-1]: dp[i][j] = 1 + dp[i-1][j-1] else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) return dp[m][n]
# 0/1 Knapsack Problem def knapsack(W, wt, val, n): dp = [[0 for x in range(W+1)] for x in range(n+1)] for i in range(n+1): for w in range(W+1): if i == 0 or w == 0: dp[i][w] = 0 elif wt[i-1] <= w: dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]) else: dp[i][w] = dp[i-1][w] return dp[n][W]