Classic DP patterns
Implement coin change, 0/1 knapsack, and climbing stairs bottom-up — three patterns that cover most 1D DP problems.
- Implement coin change (minimum coins) using bottom-up tabulation
- Implement 0/1 knapsack with a 2D DP table
- Implement climbing stairs using a rolling window
Three workhorses. Each appears in a wide family of real problems; recognising the underlying pattern matters more than memorising the code.
Three canonical problems
Coin change: the recurrence
dp[a] = minimum coins to make amount a. For each coin c, if we use one
coin of denomination c, the remaining problem is a - c, already solved.
So dp[a] = min over all coins c of (dp[a - c] + 1). Fill from dp[0] = 0
upward.
The key insight: unlike 0/1 knapsack, coins can be reused — this is an unbounded DP. The inner loop iterates over denominations, not a "take or skip" binary choice.
0/1 knapsack: take or skip
The 2D table captures a choice at each item. dp[i][w] considers only items
0 through i-1 with a weight budget of w. Two options at item i-1:
- Skip:
dp[i][w] = dp[i-1][w]— same budget, one fewer item to consider. - Take (if it fits):
dp[i][w] = dp[i-1][w - weight[i-1]] + value[i-1].
Take the maximum of the two. The "1" in "0/1" means each item can be included
at most once — hence using dp[i-1] (previous row) when taking, not dp[i].
Space optimisation for knapsack: process the weight loop in reverse when using a single 1D array. This prevents an item from being counted twice in the same pass, which would turn 0/1 into unbounded knapsack.
Climbing stairs: disguised Fibonacci
ways(n) = ways(n-1) + ways(n-2). Exactly Fibonacci with different base
cases. The rolling window brings space to O(1). This pattern appears whenever
"the number of ways to reach state n equals the sum of ways to reach two
adjacent states."
Where to go next
Next: 2D DP — longest common subsequence, edit distance, and unique paths in a grid, where the recurrence operates on a full 2D table rather than a 1D array.