0/1 Knapsack Problem
Finds the maximum value subset of items that fits within a weight capacity, where each item can be taken at most once, using dynamic programming.
Syntax
knapsack01(weights, values, capacity) Parameters
| Name | Type | Required | Description |
|---|---|---|---|
weights | number[] | Yes | Array of item weights (non-negative integers). |
values | number[] | Yes | Array of item values, parallel to weights. |
capacity | number | Yes | Maximum total weight the knapsack can hold. |
Returns
number — Maximum total value achievable without exceeding capacity.
Examples
function knapsack01(weights, values, capacity) {
const n = weights.length;
// dp[w] = max value achievable with capacity w
const dp = new Array(capacity + 1).fill(0);
for (let i = 0; i < n; i++) {
// Iterate backwards to avoid using item i twice
for (let w = capacity; w >= weights[i]; w--) {
dp[w] = Math.max(dp[w], dp[w - weights[i]] + values[i]);
}
}
return dp[capacity];
}
const weights = [2, 3, 4, 5];
const values = [3, 4, 5, 6];
const capacity = 5;
console.log(knapsack01(weights, values, capacity));
Output
7
// Reconstruct which items were chosen
function knapsack01WithItems(weights, values, capacity) {
const n = weights.length;
const dp = Array.from({length: n + 1}, () => new Array(capacity + 1).fill(0));
for (let i = 1; i <= n; i++)
for (let w = 0; w <= capacity; w++) {
dp[i][w] = dp[i-1][w];
if (weights[i-1] <= w)
dp[i][w] = Math.max(dp[i][w], dp[i-1][w-weights[i-1]] + values[i-1]);
}
// Backtrack
const chosen = [];
let w = capacity;
for (let i = n; i > 0; i--)
if (dp[i][w] !== dp[i-1][w]) { chosen.push(i-1); w -= weights[i-1]; }
return { maxValue: dp[n][capacity], items: chosen.reverse() };
}
console.log(knapsack01WithItems([2,3,4,5],[3,4,5,6],5));
Output
{ maxValue: 7, items: [ 0, 1 ] }
Notes
| Case | Time | Space |
|---------|------------|------------|
| Best | O(n·W) | O(W) |
| Average | O(n·W) | O(W) |
| Worst | O(n·W) | O(W) |
where n = number of items and W = capacity. This is **pseudo-polynomial**
— it is exponential in the input size if W is encoded in binary. The 1D
DP array (bottom-up, right-to-left) uses O(W) space vs the 2D table's
O(nW). Traversing weights right-to-left in the 1D version ensures each
item is used at most once. For the unbounded knapsack (items reusable),
iterate weights left-to-right instead.