0 1 Knapsack Problem in DSA Javascript - Time & Space Complexity
We want to understand how the time needed to solve the 0 1 Knapsack Problem changes as we add more items or increase the knapsack capacity.
The question is: How does the work grow when inputs get bigger?
Analyze the time complexity of the following code snippet.
function knapsack(weights, values, capacity) {
const n = weights.length;
const dp = Array(n + 1).fill(null).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], dp[i - 1][w - weights[i - 1]] + values[i - 1]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
return dp[n][capacity];
}
This code finds the best total value of items that fit into the knapsack without exceeding its capacity.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Nested loops over items and capacities.
- How many times: Outer loop runs
ntimes (number of items), inner loop runscapacitytimes.
Each item is checked against every capacity from 1 up to the max capacity, so work grows with both.
| Input Size (n items, capacity W) | Approx. Operations |
|---|---|
| 10 items, capacity 50 | ~ 10 * 50 = 500 |
| 100 items, capacity 1000 | ~ 100 * 1000 = 100,000 |
| 1000 items, capacity 10,000 | ~ 1000 * 10,000 = 10,000,000 |
Pattern observation: The work grows roughly by multiplying the number of items by the capacity.
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 depends only on the number of items, so it is O(n)."
[OK] Correct: The capacity also affects the time because the algorithm checks every capacity value for each item, so both matter.
Understanding this time complexity helps you explain how dynamic programming solves problems efficiently by breaking them into smaller parts, a skill valued in many coding challenges.
"What if we used recursion with memoization instead of loops? 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 total weight of selected items must not exceed the knapsack's weight limit.Final Answer:
The total value of items without exceeding the weight limit -> Option AQuick Check:
Maximize value with weight limit = B [OK]
- Confusing weight limit with value limit
- Thinking the problem maximizes number of items
- Ignoring the weight constraint
Solution
Step 1: Understand DP array initialization
We need a 2D array where each row is a separate array to avoid reference issues.Step 2: Choose correct initialization
Using Array.from with a function creates independent inner arrays, preventing shared references.Final Answer:
const dp = Array.from({ length: n + 1 }, () => Array(W + 1).fill(0)); -> Option CQuick Check:
Independent inner arrays = A [OK]
- Using fill with array directly causing shared references
- Initializing with wrong dimensions
- Forgetting to fill inner arrays
function knapsack(weights, values, W) {
const n = weights.length;
const dp = Array.from({ length: n + 1 }, () => Array(W + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let w = 1; w <= W; 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][W];
}
console.log(knapsack([1, 3, 4], [15, 50, 60], 5));Solution
Step 1: Trace DP table filling
Check items one by one and weights up to 5:
- Item 1 (weight 1, value 15): dp[1][1..5] = 15
- Item 2 (weight 3, value 50): dp[2][3] = max(15, 0+50)=50, dp[2][4]=max(15,15+50)=65, dp[2][5]=max(15,15+50)=65
- Item 3 (weight 4, value 60): dp[3][4]=max(65,0+60)=65, dp[3][5]=max(65,15+60)=75Step 2: Find final answer
The maximum value for weight 5 is dp[3][5] = 75.Final Answer:
75 -> Option DQuick Check:
Max value at W=5 = 75 [OK]
- Adding values without checking weight limit
- Confusing indices in dp array
- Forgetting to compare including vs excluding item
function knapsack(weights, values, W) {
const n = weights.length;
const dp = Array.from({ length: n + 1 }, () => Array(W + 1).fill(0));
for (let i = 1; i <= n; i++) {
for (let w = 1; w <= W; w++) {
if (weights[i] <= w) {
dp[i][w] = Math.max(dp[i - 1][w], dp[i - 1][w - weights[i]] + values[i]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
return dp[n][W];
}Solution
Step 1: Identify index error in array access
Arrays in JavaScript are zero-indexed, but loop starts at 1, so weights[i] accesses out-of-bound or wrong element.Step 2: Correct index usage
Use weights[i - 1] and values[i - 1] to access correct item corresponding to dp row i.Final Answer:
Change weights[i] and values[i] to weights[i - 1] and values[i - 1] -> Option AQuick Check:
Fix index offset = D [OK]
- Using wrong indices causing undefined values
- Changing loop start incorrectly
- Incorrect dp initialization
Note: You can only take each item once.
Solution
Step 1: Consider all item combinations within weight limit 10
Possible combinations:
- Items 1,2,3: weights 2+3+5=10, values 10+5+15=30 (exceeds capacity? No, equals 10)
- Items 1,3,4: weights 2+5+7=14 (exceeds 10)
- Items 2,3,4: weights 3+5+7=15 (exceeds 10)
- Items 1,4: weights 2+7=9, values 10+7=17
- Items 3 alone: weight 5, value 15
- Items 1,2,4: weights 2+3+7=12 (exceeds 10)Step 2: Find max value without exceeding weight
Best valid combination is items 1,2,3 with total weight 10 and value 30. But since weight is exactly 10, it's valid.
Check if any other combination gives more value:
Items 1,3: weight 7, value 25
Items 3,4: weight 12 (exceeds)
So max value is 30.Final Answer:
30 -> Option BQuick Check:
Max value with W=10 = 30 [OK]
- Ignoring exact weight limit equality
- Adding values of items exceeding capacity
- Missing best combination
Ready to prove it?
Pass the test and this pattern moves unknown
