Skip to content

Commit 8a8d1e2

Browse files
committed
feat: Add 0/1 Knapsack and its tabulation implementation with their corresponding tests
1 parent 3b8c5df commit 8a8d1e2

File tree

4 files changed

+105
-102
lines changed

4 files changed

+105
-102
lines changed
Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,38 @@
11
package com.thealgorithms.dynamicprogramming;
22

33
/**
4-
* Class to solve the 0/1 Knapsack Problem using recursion.
4+
* The {@code ZeroOneKnapsack} class provides a method to solve the classic 0/1 Knapsack problem.
5+
* It returns the maximum value that can be obtained by selecting items within the weight limit.
56
*
6-
* The 0/1 Knapsack problem is a classic dynamic programming problem
7-
* where we are given weights and values of `n` items. We need to put
8-
* these items in a knapsack of capacity `W` to get the maximum total value
9-
* in the knapsack. We can either include an item or exclude it — but cannot
10-
* include it more than once.
7+
* Problem Description: Given weights and values of n items, put these items in a knapsack of capacity W
8+
* such that the total value is maximized. You cannot break an item, either pick the complete item or don't pick it.
119
*
12-
* Time Complexity: O(2^n) in worst case for the pure recursive approach (due to overlapping subproblems).
13-
* Using memoization or bottom-up dynamic programming reduces the time complexity to O(nW).
14-
*
15-
* Example:
16-
* val[] = {15, 14, 10, 45, 30}
17-
* wt[] = {2, 5, 1, 3, 4}
18-
* W = 7
19-
* Output: 75
10+
* https://en.wikipedia.org/wiki/Knapsack_problem
2011
*/
21-
public class ZeroOneKnapsack {
12+
public final class ZeroOneKnapsack {
13+
private ZeroOneKnapsack() {
14+
}
2215

2316
/**
2417
* Solves the 0/1 Knapsack problem using recursion.
2518
*
26-
* @param val Array of item values (must have length at least n)
27-
* @param wt Array of item weights (must have length at least n)
28-
* @param W Total capacity of the knapsack
29-
* @param n Number of items to consider
30-
* @return The maximum value that can be obtained
19+
* @param values the array containing values of the items
20+
* @param weights the array containing weights of the items
21+
* @param capacity the total capacity of the knapsack
22+
* @param n the number of items
23+
* @return the maximum total value achievable within the given weight limit
3124
*/
32-
public static int knapsack(int[] val, int[] wt, int W, int n) {
33-
if (val == null || wt == null || val.length != wt.length) {
34-
throw new IllegalArgumentException("Value and weight arrays must be non-null and of equal length.");
35-
}
36-
if (W == 0 || n == 0) {
25+
public static int KnapsackCompute(int[] values, int[] weights, int capacity, int n) {
26+
if (n == 0 || capacity == 0) {
3727
return 0;
3828
}
39-
if (wt[n - 1] <= W) {
40-
// Include the current item
41-
int include = val[n - 1] + knapsack(val, wt, W - wt[n - 1], n - 1);
42-
// Exclude the current item
43-
int exclude = knapsack(val, wt, W, n - 1);
29+
30+
if (weights[n - 1] <= capacity) {
31+
int include = values[n - 1] + KnapsackCompute(values, weights, capacity - weights[n - 1], n - 1);
32+
int exclude = KnapsackCompute(values, weights, capacity, n - 1);
4433
return Math.max(include, exclude);
4534
} else {
46-
// Cannot include the item, move to next
47-
return knapsack(val, wt, W, n - 1);
35+
return KnapsackCompute(values, weights, capacity, n - 1);
4836
}
4937
}
5038
}
Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,49 @@
11
package com.thealgorithms.dynamicprogramming;
22

33
/**
4-
* Dynamic Programming approach for solving 0-1 Knapsack problem using tabulation.
5-
*
6-
* Problem Statement:
7-
* Given weights and values of n items, put these items in a knapsack of capacity W
8-
* to get the maximum total value in the knapsack. You cannot break an item.
4+
* The {@code ZeroOneKnapsackTab} class provides a method to solve the 0-1 Knapsack problem
5+
* using dynamic programming (tabulation approach).
96
*
10-
* Time Complexity: O(n * W)
11-
* Space Complexity: O(n * W)
7+
* <p>0-1 Knapsack Problem -
8+
* Given weights and values of n items, and a maximum weight W,
9+
* determine the maximum total value of items that can be included in the knapsack
10+
* such that their total weight does not exceed W. Each item can be picked only once.
11+
*
12+
* Problem Link: https://www.geeksforgeeks.org/0-1-knapsack-problem-dp-10/
1213
*/
13-
public class ZeroOneKnapsackTab {
14+
public final class ZeroOneKnapsackTab {
15+
16+
private ZeroOneKnapsackTab() {
17+
// prevent instantiation
18+
}
1419

1520
/**
16-
* Solves the 0-1 Knapsack problem using a tabulation approach (bottom-up DP).
21+
* Solves the 0-1 Knapsack problem using the bottom-up tabulation technique.
1722
*
18-
* @param val The values of the items
19-
* @param wt The weights of the items
20-
* @param W The total capacity of the knapsack
21-
* @param n The number of items
22-
* @return The maximum value that can be put in a knapsack of capacity W
23+
* @param val the values of the items
24+
* @param wt the weights of the items
25+
* @param W the total capacity of the knapsack
26+
* @param n the number of items
27+
* @return the maximum value that can be put in the knapsack
2328
*/
24-
public static int knapsackTab(int[] val, int[] wt, int W, int n) {
29+
public static int kcompute(int[] val, int[] wt, int W, int n) {
2530
int[][] dp = new int[n + 1][W + 1];
2631

2732
for (int i = 1; i <= n; i++) {
28-
int v = val[i - 1]; // value of current item
29-
int w = wt[i - 1]; // weight of current item
30-
for (int j = 1; j <= W; j++) {
31-
if (w <= j) {
32-
int include = v + dp[i - 1][j - w];
33-
int exclude = dp[i - 1][j];
34-
dp[i][j] = Math.max(include, exclude);
33+
int value = val[i - 1];
34+
int weight = wt[i - 1];
35+
36+
for (int w = 1; w <= W; w++) {
37+
if (weight <= w) {
38+
int include = value + dp[i - 1][w - weight];
39+
int exclude = dp[i - 1][w];
40+
dp[i][w] = Math.max(include, exclude);
3541
} else {
36-
dp[i][j] = dp[i - 1][j];
42+
dp[i][w] = dp[i - 1][w];
3743
}
3844
}
3945
}
46+
4047
return dp[n][W];
4148
}
4249
}
Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,58 @@
11
package com.thealgorithms.dynamicprogramming;
22

3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
35
import org.junit.jupiter.api.Test;
4-
import static org.junit.jupiter.api.Assertions.*;
56

67
/**
7-
* Unit tests for the ZeroOneKnapsackTab class.
8+
* Test class for {@code ZeroOneKnapsackTab}.
89
*/
9-
public class ZeroOneKnapsackTabTest {
10+
public class ZeroOneknapsackTabTest {
1011

1112
/**
12-
* Test knapsackTab with a typical set of values and weights.
13-
* Checks if the maximum value for the given capacity is correct.
13+
* Tests the 0-1 Knapsack tabulation approach with known values.
1414
*/
1515
@Test
16-
public void testKnapsackTab() {
17-
int[] val = {15, 14, 10, 45, 30};
18-
int[] wt = {2, 5, 1, 3, 4};
19-
int W = 7;
20-
int expected = 75;
21-
assertEquals(expected, ZeroOneKnapsackTab.knapsackTab(val, wt, W, val.length));
16+
public void testKnownValues() {
17+
int[] val = {60, 100, 120};
18+
int[] wt = {10, 20, 30};
19+
int W = 50;
20+
int n = val.length;
21+
22+
// Expected result is 220 (items with weight 20 and 30)
23+
assertEquals(220, ZeroOneKnapsackTab.kcompute(val, wt, W, n), "Maximum value for capacity 50 should be 220.");
24+
}
25+
26+
@Test
27+
public void testZeroCapacity() {
28+
int[] val = {10, 20, 30};
29+
int[] wt = {1, 1, 1};
30+
int W = 0;
31+
int n = val.length;
32+
33+
// With zero capacity, the result should be 0
34+
assertEquals(0, ZeroOneKnapsackTab.kcompute(val, wt, W, n), "Maximum value for capacity 0 should be 0.");
2235
}
2336

24-
/**
25-
* Test knapsackTab with empty arrays.
26-
* Should return 0 as there are no items to include.
27-
*/
2837
@Test
29-
public void testKnapsackTabEmpty() {
38+
public void testZeroItems() {
3039
int[] val = {};
3140
int[] wt = {};
3241
int W = 10;
33-
int expected = 0;
34-
assertEquals(expected, ZeroOneKnapsackTab.knapsackTab(val, wt, W, 0));
42+
int n = val.length;
43+
44+
// With no items, the result should be 0
45+
assertEquals(0, ZeroOneKnapsackTab.kcompute(val, wt, W, n), "Maximum value with no items should be 0.");
3546
}
3647

37-
/**
38-
* Test knapsackTab with zero capacity.
39-
* Should return 0 as no items can be included.
40-
*/
4148
@Test
42-
public void testKnapsackTabZeroCapacity() {
43-
int[] val = {10, 20, 30};
44-
int[] wt = {1, 1, 1};
45-
int W = 0;
46-
int expected = 0;
47-
assertEquals(expected, ZeroOneKnapsackTab.knapsackTab(val, wt, W, val.length));
49+
public void testExactFit() {
50+
int[] val = {5, 10, 15};
51+
int[] wt = {1, 2, 3};
52+
int W = 6;
53+
int n = val.length;
54+
55+
// All items fit exactly into capacity 6
56+
assertEquals(30, ZeroOneKnapsackTab.kcompute(val, wt, W, n), "Maximum value for exact fit should be 30.");
4857
}
4958
}
Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,59 @@
11
package com.thealgorithms.dynamicprogramming;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
45
import org.junit.jupiter.api.Test;
56

67
/**
7-
* Unit tests for the ZeroOneKnapsack algorithm.
8+
* Test class for {@code ZeroOneKnapsack}.
89
*/
910
public class ZeroOneKnapsackTest {
1011

1112
/**
12-
* Test the knapsack algorithm with a basic example.
13+
* Tests the knapsack computation for a basic example.
1314
*/
1415
@Test
15-
void testKnapsackBasic() {
16+
public void testKnapsackBasic() {
1617
int[] val = {15, 14, 10, 45, 30};
1718
int[] wt = {2, 5, 1, 3, 4};
1819
int W = 7;
19-
int expected = 75;
20-
assertEquals(expected, ZeroOneKnapsack.knapsack(val, wt, W, val.length));
20+
assertEquals(75, ZeroOneKnapsack.KnapsackCompute(val, wt, W, val.length),
21+
"Expected maximum value is 75.");
2122
}
2223

2324
/**
24-
* Test the knapsack algorithm when the knapsack capacity is zero.
25-
* Expected result is zero since nothing can be added.
25+
* Tests the knapsack computation when the knapsack capacity is zero.
2626
*/
2727
@Test
28-
void testZeroCapacity() {
28+
public void testZeroCapacity() {
2929
int[] val = {10, 20, 30};
3030
int[] wt = {1, 1, 1};
3131
int W = 0;
32-
int expected = 0;
33-
assertEquals(expected, ZeroOneKnapsack.knapsack(val, wt, W, val.length));
32+
assertEquals(0, ZeroOneKnapsack.KnapsackCompute(val, wt, W, val.length),
33+
"Expected maximum value is 0 for zero capacity.");
3434
}
3535

3636
/**
37-
* Test the knapsack algorithm when there are no items.
38-
* Expected result is zero since there is nothing to add.
37+
* Tests the knapsack computation when there are no items.
3938
*/
4039
@Test
41-
void testNoItems() {
40+
public void testNoItems() {
4241
int[] val = {};
4342
int[] wt = {};
4443
int W = 10;
45-
int expected = 0;
46-
assertEquals(expected, ZeroOneKnapsack.knapsack(val, wt, W, 0));
44+
assertEquals(0, ZeroOneKnapsack.KnapsackCompute(val, wt, W, 0),
45+
"Expected maximum value is 0 when no items are available.");
4746
}
4847

4948
/**
50-
* Test the knapsack algorithm with items that exactly fit the knapsack.
49+
* Tests the knapsack computation when items exactly fit the capacity.
5150
*/
5251
@Test
53-
void testExactFit() {
52+
public void testExactFit() {
5453
int[] val = {60, 100, 120};
5554
int[] wt = {10, 20, 30};
5655
int W = 50;
57-
int expected = 220;
58-
assertEquals(expected, ZeroOneKnapsack.knapsack(val, wt, W, val.length));
56+
assertEquals(220, ZeroOneKnapsack.KnapsackCompute(val, wt, W, val.length),
57+
"Expected maximum value is 220 for exact fit.");
5958
}
6059
}

0 commit comments

Comments
 (0)