Master the 0/1 Knapsack dynamic programming decision pattern to solve subset sum, partition, and coin change problems.
Learn how dynamic arrays achieve O(1) amortized insertion, contiguous memory layout, and geometric doubling strategies.
Given $N$ items where each item has a weight and a value, determine the maximum value you can carry in a knapsack of maximum weight capacity $W$.
For item $i$ with weight $w$ and value $v$ at capacity $c$: $$ ext[i][c] = max( ext[i - 1][c], ext[i - 1][c - w] + v)$$
function knapsack01(weights, values, capacity) {
const n = weights.length;
// 1D Array Space Optimization (Iterate backwards to prevent reusing same item!)
const dp = new Array(capacity + 1).fill(0);
for (let i = 0; i < n; i++) {
const w = weights[i];
const v = values[i];
// Must iterate backwards from capacity down to w!
for (let c = capacity; c >= w; c--) {
dp[c] = Math.max(dp[c], dp[c - w] + v);
}
}
return dp[capacity];
}
const weights = [2, 3, 4, 5];
const values = [3, 4, 5, 6];
console.log(knapsack01(weights, values, 5)); // Output: 7 (Items with weights 2 and 3)
Find the fewest coins needed to make up a given target amount (infinite coin reuse):
function coinChange(coins, amount) {
const dp = new Array(amount + 1).fill(Infinity);
dp[0] = 0; // Base case: 0 amount requires 0 coins
for (const coin of coins) {
// Iterate forward because coins can be reused!
for (let a = coin; a <= amount; a++) {
dp[a] = Math.min(dp[a], dp[a - coin] + 1);
}
}
return dp[amount] === Infinity ? -1 : dp[amount];
}
console.log(coinChange([1, 2, 5], 11)); // Output: 3 (5 + 5 + 1)
c = capacity down to w).c = w up to capacity).Use knapsack patterns for subset partition problems. Next, let's explore Longest Common Subsequence (LCS)!