0 1 Knapsack Problem in DSA Typescript - Time & Space Complexity
We want to understand how the time needed to solve the 0 1 Knapsack problem grows as the number of items and the knapsack capacity increase.
How does the number of steps change when we add more items or increase the capacity?
Analyze the time complexity of the following code snippet.
function knapsack(weights: number[], values: number[], capacity: number): number {
const n = weights.length;
const dp: number[][] = Array.from({ length: n + 1 }, () => Array(capacity + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let w = 1; w <= capacity; w++) {
if (weights[i - 1] <= w) {
dp[i][w] = Math.max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
return dp[n][capacity];
}
This code solves the 0 1 Knapsack problem using dynamic programming by filling a table of size (number of items + 1) by (capacity + 1).
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Nested loops over items and capacity filling the dp table.
- How many times: Outer loop runs n times (number of items), inner loop runs capacity times.
As we add more items or increase capacity, the number of steps grows by multiplying these two factors.
| Input Size (n items, capacity W) | Approx. Operations |
|---|---|
| 10 items, capacity 50 | About 10 * 50 = 500 steps |
| 100 items, capacity 1000 | About 100 * 1000 = 100,000 steps |
| 1000 items, capacity 10,000 | About 1000 * 10,000 = 10,000,000 steps |
Pattern observation: The steps grow roughly by multiplying the number of items by the capacity, so doubling either doubles the work.
Time Complexity: O(n * W)
This means the time needed grows proportionally with both the number of items and the knapsack capacity.
[X] Wrong: "The time complexity depends only on the number of items, not the capacity."
[OK] Correct: The inner loop runs for every capacity value up to W, so capacity directly affects the total steps.
Understanding this time complexity helps you explain how dynamic programming improves over brute force and why capacity matters in performance.
"What if we used a recursive solution without memoization? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem goal
The 0 1 Knapsack problem tries to select items to maximize total value without exceeding the weight capacity.Step 2: Identify the constraint
The constraint is the maximum weight the knapsack can carry, so total weight must not exceed this limit.Final Answer:
The total value of items without exceeding the weight limit -> Option DQuick Check:
Maximize value under weight limit = The total value of items without exceeding the weight limit [OK]
- Confusing weight limit with value limit
- Trying to maximize weight instead of value
- Ignoring the weight constraint
Solution
Step 1: Check parameter types
Weights and values should be arrays of numbers, capacity a number, and return type a number representing max value.Step 2: Match correct signature
function knapsack(weights: number[], values: number[], capacity: number): number matches this: arrays for weights and values, number for capacity, returns number.Final Answer:
function knapsack(weights: number[], values: number[], capacity: number): number -> Option AQuick Check:
Correct types and return = function knapsack(weights: number[], values: number[], capacity: number): number [OK]
- Using string types instead of number
- Swapping array and single number types
- Incorrect return type
const weights = [1, 3, 4];
const values = [15, 50, 60];
const capacity = 5;
function knapsack(w: number[], v: number[], c: number): number {
const n = w.length;
const dp = Array(n + 1).fill(null).map(() => Array(c + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= c; j++) {
if (w[i - 1] <= j) {
dp[i][j] = Math.max(dp[i - 1][j], v[i - 1] + dp[i - 1][j - w[i - 1]]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[n][c];
}
console.log(knapsack(weights, values, capacity));Solution
Step 1: Understand DP table filling
For capacity 5, items: (1,15), (3,50), (4,60). Check combinations: - Item1 + Item2: weight 4, value 65 - Item3 alone: weight 4, value 60 - Item2 alone: weight 3, value 50 - Item1 + Item3: weight 5, value 75Step 2: Find max value under capacity
Item1 + Item3 total weight 5, value 75 is max possible under capacity 5.Final Answer:
75 -> Option CQuick Check:
Max value with capacity 5 = 75 [OK]
- Ignoring combined items
- Choosing single highest value item only
- Miscomputing weights or values
function knapsack(weights: number[], values: number[], capacity: number): number {
const n = weights.length;
const dp = Array(n + 1).fill([]).map(() => Array(capacity + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let w = 1; w <= capacity; w++) {
if (weights[i - 1] <= w) {
dp[i][w] = Math.max(dp[i - 1][w], values[i - 1] + dp[i - 1][w - weights[i - 1]]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
return dp[n][capacity];
}Solution
Step 1: Examine the dp array initialization
The code uses Array(n + 1).fill([]).map(() => Array(capacity + 1).fill(0)), but fill([]) fills all elements with the same array reference, which is then overridden by map creating new arrays. However, the initial fill([]) is unnecessary and can cause confusion or bugs if map is removed.Step 2: Correct initialization
Better to initialize dp as Array(n + 1).fill(null).map(() => Array(capacity + 1).fill(0)) or directly with map to ensure independent arrays without shared references.Final Answer:
Change Array(n + 1).fill([]) to Array(n + 1).fill([]).map(() => Array(capacity + 1).fill(0)) -> Option BQuick Check:
Ensure dp rows are independent arrays to avoid shared reference bugs [OK]
- Assuming fill([]) creates independent arrays
- Ignoring shared reference issues
- Claiming no bug when shared references exist
Solution
Step 1: Calculate total weights and values for each option
Items with weights 2, 3, and 5 (total value 30): weights 2+3+5=10, values 10+5+15=30 Items with weights 3 and 7 (total value 12): weights 3+7=10, values 5+7=12 Items with weights 5 and 7 (total value 22): weights 5+7=12 (exceeds capacity) Items with weights 2 and 7 (total value 17): weights 2+7=9, values 10+7=17Step 2: Choose max value under capacity
Items with weights 2, 3, and 5 (total value 30) fits capacity exactly and has highest value 30.Final Answer:
Items with weights 2, 3, and 5 (total value 30) -> Option AQuick Check:
Max value under capacity 10 = 30 [OK]
- Choosing items exceeding capacity
- Ignoring combined item values
- Selecting fewer items with lower total value
Ready to prove it?
Pass the test and this pattern moves unknown
