What is Dynamic Programming?
Dynamic Programming (DP) is an optimization technique that solves complex problems by breaking them into simpler subproblems. It stores results to avoid redundant calculations.
When to Use DP
DP applies when a problem has optimal substructure and overlapping subproblems. Classic examples: Fibonacci, knapsack, longest common subsequence.
Top-Down vs Bottom-Up
def fib_memo(n, memo={}):
if n in memo: return memo[n]
if n <= 1: return n
memo[n] = fib_memo(n-1) + fib_memo(n-2)
return memo[n]
def fib_tab(n):
if n <= 1: return 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]Pattern 1: Linear DP
def climb_stairs(n):
if n<=2: return 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]
def rob(nums):
if not nums: return 0
if len(nums)==1: return nums[0]
dp=[0]*len(nums)
dp[0]=nums[0]
dp[1]=max(nums[0],nums[1])
for i in range(2,len(nums)):
dp[i]=max(dp[i-1],dp[i-2]+nums[i])
return dp[-1]Pattern 2: Grid DP
def unique_paths(m,n):
dp=[[1]*n for _ in range(m)]
for i in range(1,m):
for j in range(1,n):
dp[i][j]=dp[i-1][j]+dp[i][j-1]
return dp[m-1][n-1]Pattern 3: Knapsack
def knapsack(weights,values,cap):
n=len(weights)
dp=[[0]*(cap+1) for _ in range(n+1)]
for i in range(1,n+1):
for w in range(1,cap+1):
if weights[i-1]<=w:
dp[i][w]=max(values[i-1]+dp[i-1][w-weights[i-1]],dp[i-1][w])
else:
dp[i][w]=dp[i-1][w]
return dp[n][cap]Tips
Don t forget base cases. Initialize DP arrays carefully. Watch for off-by-one errors. Verify recurrence relation before implementing. Reduce space by noting current state only depends on recent states.
Comments