0/1 Knapsack
Given items with weights and values, maximize value within a weight limit. For each item: include it (value + dp[remaining weight]) or skip it (dp without it). dp[i][w] = max of taking or skipping item i at weight w.
Each item is take or leave with a shared budget, so a table over items and capacity. In 1D I must iterate capacity downward or items get reused.
How It Works
0/1 Knapsack maximizes total value when each item can be taken at most once under a weight budget. Define dp[i][w] as the best value using the first i items with capacity w. For item i you either skip it (dp[i-1][w]) or, if it fits, take it (value[i] + dp[i-1][w - weight[i]]). Trying both and keeping the max examines all 2^n subsets implicitly in only n×W table cells.
The result is O(nW) time and, since each row reads only the previous row, O(W) space. Provided you iterate weights backward so an item is not reused within its own row. This pseudo-polynomial bound is why knapsack is tractable for moderate capacities despite subset selection being NP-hard in general.
Step-by-Step Visualization
Code
Tips & Gotchas
Practice Problems
- 1Partition Equal Subset Sum
- 2Target Sum
- 3Last Stone Weight II
- 4Ones and Zeroes
About the 2D DP Pattern
The state needs two variables, typically two indices (comparing two sequences), or a position in a grid. dp[i][j] depends on dp[i-1][j], dp[i][j-1], or dp[i-1][j-1]. Fills a 2D table.
The framework: 1) Define state (what changes between subproblems). 2) Write recurrence relation. 3) Identify base cases. 4) Decide iteration order. Most DP is either 1D, 2D, or interval-based.
Common Dynamic Programming Interview Problems
- Climbing Stairs
- Coin Change
- Longest Common Subsequence
- 0/1 Knapsack
- Edit Distance
- House Robber
- Longest Increasing Subsequence
- Word Break
Frequently Asked Questions
Why must the 1D-space version loop capacity from high to low?
Iterating backward guarantees dp[w - weight] still holds the previous item row's value, so each item is counted at most once. Looping forward would let the current item contribute multiple times, which silently turns 0/1 knapsack into unbounded knapsack.
How do I spot a knapsack hiding inside a problem statement?
Look for a fixed budget or target (capacity, sum, count) and per-element include/exclude decisions. Partition Equal Subset Sum, for example, is knapsack with target = totalSum / 2 and a boolean 'can we hit exactly this sum' table.
Is O(nW) truly polynomial time?
It is pseudo-polynomial: W is a numeric value, so its bit-length is log W, and O(nW) is exponential in the input's encoded size. That is why knapsack is NP-hard in theory yet perfectly practical when capacities are in the thousands.