1D DP Space Optimization
# Fibonacci: O(n) -> O(1) space
def fib(n: int) -> int:
if n int:
prev2 = prev1 = 0
for n in nums:
prev2, prev1 = prev1, max(prev1, prev2 + n)
return prev1
# Coin Change (LC 322): only need current row
def coin_change(coins: list[int], amount: int) -> int:
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for a in range(coin, amount + 1):
dp[a] = min(dp[a], dp[a - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
2D DP Space Optimization – Rolling Array
# LCS: O(m*n) -> O(min(m,n)) space
def lcs(s1: str, s2: str) -> int:
if len(s1) int:
dp = [0] * (W + 1)
for w, v in zip(weights, values):
for cap in range(W, w - 1, -1): # reverse to avoid reuse
dp[cap] = max(dp[cap], dp[cap - w] + v)
return dp[W]
Bitmask DP – Subset State Representation
# Traveling Salesman Problem (TSP) with bitmask DP
# dp[mask][i] = min cost to visit all cities in mask, ending at city i
def tsp(dist: list[list[int]]) -> int:
n = len(dist)
INF = float('inf')
dp = [[INF] * n for _ in range(1 << n)]
dp[1][0] = 0 # start at city 0
for mask in range(1 <> u & 1):
continue
for v in range(n):
if mask >> v & 1:
continue # already visited
new_mask = mask | (1 << v)
dp[new_mask][v] = min(dp[new_mask][v], dp[mask][u] + dist[u][v])
full = (1 << n) - 1
return min(dp[full][i] + dist[i][0] for i in range(1, n))
# O(2^n * n^2) time - feasible for n int:
n = len(jobs)
subset_sum = [0] * (1 << n)
for mask in range(1 <> i & 1:
subset_sum[mask] = subset_sum[mask ^ (1 << i)] + jobs[i]
dp = [float('inf')] * (1 << n)
dp[0] = 0
for mask in range(1, 1 << n):
sub = mask
while sub:
dp[mask] = min(dp[mask], max(dp[mask ^ sub], subset_sum[sub]))
sub = (sub - 1) & mask
return dp[(1 << n) - 1]
Interval DP – Merging Ranges
# Burst Balloons (LC 312): dp[i][j] = max coins from bursting all balloons i..j
def max_coins(nums: list[int]) -> int:
nums = [1] + nums + [1] # add boundary sentinels
n = len(nums)
dp = [[0] * n for _ in range(n)]
for length in range(2, n): # interval length
for left in range(0, n - length):
right = left + length
for k in range(left + 1, right): # last balloon to burst
dp[left][right] = max(
dp[left][right],
nums[left] * nums[k] * nums[right] +
dp[left][k] + dp[k][right]
)
return dp[0][n-1]
# Key insight: think of k as the LAST balloon burst, not first
# Matrix Chain Multiplication: minimum multiplications
def matrix_chain(dims: list[int]) -> int:
n = len(dims) - 1 # n matrices
dp = [[0] * n for _ in range(n)]
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
dp[i][j] = float('inf')
for k in range(i, j):
cost = dp[i][k] + dp[k+1][j] + dims[i]*dims[k+1]*dims[j+1]
dp[i][j] = min(dp[i][j], cost)
return dp[0][n-1]
Meta coding interviews heavily test dynamic programming. Review DP optimization patterns used in Meta interview: dynamic programming problems.
Atlassian coding interviews include DP optimization problems. See common patterns for Atlassian interview: dynamic programming and optimization problems.
Coinbase interviews test DP and combinatorics problems. Review optimization patterns for Coinbase interview: dynamic programming and combinatorics.