By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
(Complete Guide for FAANG-Level Interviews)
"The 0/1 Knapsack problem is the ultimate test of dynamic programming mastery—it appears in 1 out of every 3 onsite interviews at top-tier companies. Nail it, and you prove you can break down complex optimization problems into clean, reusable DP patterns."
Before tackling 0/1 Knapsack, ensure you understand: 1. Dynamic Programming (DP) Basics – Memoization vs. tabulation, state transitions, and recurrence relations. 2. Time & Space Complexity Analysis – How to compute and optimize for O(nW) vs. O(n) space. 3. Recursive Backtracking – How to model decisions (take/don’t take) and base cases.
dp[i][w] = max value using first
items with capacity
memo[i][w] = max(include, exclude)
dp[w] = max(dp[w], dp[w - weight[i]] + value[i])
dp[i][w] = max(dp[i-1][w], dp[i-1][w - weight[i]] + value[i])
w
W
0
weight[i] > W
n = 0
(Repeatable mental checklist for every 0/1 Knapsack problem.)
Identify n (number of items), W (capacity), weights[], values[].
n
weights[]
values[]
Define the DP State
Base case: dp[0][w] = 0 (no items), dp[i][0] = 0 (zero capacity).
dp[0][w] = 0
dp[i][0] = 0
Write the Recurrence Relation
i
dp[i-1][w]
dp[i-1][w - weight[i]] + value[i]
weight[i] <= w
Final: dp[i][w] = max(Option 1, Option 2)
dp[i][w] = max(Option 1, Option 2)
Choose Implementation Style
Bottom-Up (Tabulation): Iterative + 2D/1D array (space-optimized).
Optimize Space (If Needed)
Iterate w from W to 0 to avoid overwriting.
Handle Edge Cases
W = 0
weight[i] > W → Skip item.
Test with Small Inputs
Manually verify dp table for n=2, W=3.
dp
n=2, W=3
Analyze Complexity
O(nW)
O(W)
Problem: Given weights = [1, 2, 3], values = [6, 10, 12], W = 5, find max value.
weights = [1, 2, 3]
values = [6, 10, 12]
W = 5
Fill DP Table: | i\w | 0 | 1 | 2 | 3 | 4 | 5 | |-----|---|---|---|---|---|---| | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 0 | 6 | 6 | 6 | 6 | 6 | | 2 | 0 | 6 | 10| 16| 16| 16| | 3 | 0 | 6 | 10| 16| 18| 22|
Result: dp[3][5] = 22.
dp[3][5] = 22
def knapsack(weights, values, W): n = len(weights) memo = [[-1] (W + 1) for _ in range(n + 1)] def dp(i, w): if i == 0 or w == 0: return 0 if memo[i][w] != -1: return memo[i][w] if weights[i-1] > w: memo[i][w] = dp(i-1, w) else: memo[i][w] = max(dp(i-1, w), dp(i-1, w - weights[i-1]) + values[i-1]) return memo[i][w] return dp(n, W) print(knapsack([1, 2, 3], [6, 10, 12], 5)) # Output: 22
def knapsack(weights, values, W): dp = [0] (W + 1) for i in range(len(weights)): for w in range(W, weights[i] - 1, -1): dp[w] = max(dp[w], dp[w - weights[i]] + values[i]) return dp[W] print(knapsack([1, 2, 3], [6, 10, 12], 5)) # Output: 22
dp[i][w]
Problem: Given nums = [1, 2, 3, 4], target = 6, count subsets that sum to target.
nums = [1, 2, 3, 4]
target = 6
target
dp[i][s] = number of subsets using first
items that sum to
dp[0][0] = 1
dp[0][s>0] = 0
dp[i][s] = dp[i-1][s] + dp[i-1][s - nums[i-1]]
s >= nums[i-1]
Fill DP Table: | i\s | 0 | 1 | 2 | 3 | 4 | 5 | 6 | |-----|---|---|---|---|---|---|---| | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | | 2 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | | 3 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | | 4 | 1 | 1 | 1 | 2 | 2 | 2 | 3 |
Result: dp[4][6] = 2 (subsets: [1,2,3], [2,4]).
dp[4][6] = 2
[1,2,3]
[2,4]
def count_subsets(nums, target): dp = [0] (target + 1) dp[0] = 1 for num in nums: for s in range(target, num - 1, -1): dp[s] += dp[s - num] return dp[target] print(count_subsets([1, 2, 3, 4], 6)) # Output: 2
Problem: Given nums = [1, 6, 11, 5], partition into two subsets with minimum difference.
nums = [1, 6, 11, 5]
S/2
S = sum(nums)
dp[i][s] = True if sum
can be formed with first
dp[0][0] = True
dp[i][s] = dp[i-1][s] or dp[i-1][s - nums[i-1]]
s
S//2
dp[n][s]
True
abs(S - 2s)
def min_subset_diff(nums): total = sum(nums) n = len(nums) dp = [False] (total // 2 + 1) dp[0] = True for num in nums: for s in range(total // 2, num - 1, -1): dp[s] = dp[s] or dp[s - num] for s in range(total // 2, -1, -1): if dp[s]: return abs(total - 2 s) return total print(min_subset_diff([1, 6, 11, 5])) # Output: 1 (11 vs 12)
if weight[i] > w: dp[i][w] = dp[i-1][w]
dp[w]
range(n)
range(1, n+1)
1
"Alright, let’s lock this in. For 0/1 Knapsack, remember: 1. Define dp[i][w] as the max value using the first i items with capacity w. 2. Recurrence: max(exclude, include) where include = dp[i-1][w - weight[i]] + value[i]. 3. Base cases: dp[0][w] = 0, dp[i][0] = 0. 4. Optimize space: Use 1D array and iterate w backward. 5. Edge cases: Skip items where weight[i] > W.
max(exclude, include)
include = dp[i-1][w - weight[i]] + value[i]
Test with small inputs, and you’ll catch 90% of bugs. Now go crush that interview!
This framework is battle-tested—use it, and you’ll solve any 0/1 Knapsack problem under pressure. ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.