Skip to content

Add tests, remove main, improve docs in BruteForceKnapsack #5641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@
* [StrassenMatrixMultiplicationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/StrassenMatrixMultiplicationTest.java)
* dynamicprogramming
* [BoardPathTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/BoardPathTest.java)
* [BruteForceKnapsackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/BruteForceKnapsackTest.java)
* [CatalanNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/CatalanNumberTest.java)
* [ClimbStairsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/ClimbStairsTest.java)
* [CountFriendsPairingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/CountFriendsPairingTest.java)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,67 @@
package com.thealgorithms.dynamicprogramming;

/* A Naive recursive implementation
of 0-1 Knapsack problem */
/**
* A naive recursive implementation of the 0-1 Knapsack problem.
*
* <p>The 0-1 Knapsack problem is a classic optimization problem where you are
* given a set of items, each with a weight and a value, and a knapsack with a
* fixed capacity. The goal is to determine the maximum value that can be
* obtained by selecting a subset of the items such that the total weight does
* not exceed the knapsack's capacity. Each item can either be included (1) or
* excluded (0), hence the name "0-1" Knapsack.</p>
*
* <p>This class provides a brute-force recursive approach to solving the
* problem. It evaluates all possible combinations of items to find the optimal
* solution, but this approach has exponential time complexity and is not
* suitable for large input sizes.</p>
*
* <p><b>Time Complexity:</b> O(2^n), where n is the number of items.</p>
*
* <p><b>Space Complexity:</b> O(n), due to the recursive function call stack.</p>
*/
public final class BruteForceKnapsack {
private BruteForceKnapsack() {
}
// Returns the maximum value that
// can be put in a knapsack of
// capacity W

/**
* Solves the 0-1 Knapsack problem using a recursive brute-force approach.
*
* @param w the total capacity of the knapsack
* @param wt an array where wt[i] represents the weight of the i-th item
* @param val an array where val[i] represents the value of the i-th item
* @param n the number of items available for selection
* @return the maximum value that can be obtained with the given capacity
*
* <p>The function uses recursion to explore all possible subsets of items.
* For each item, it has two choices: either include it in the knapsack
* (if it fits) or exclude it. It returns the maximum value obtainable
* through these two choices.</p>
*
* <p><b>Base Cases:</b>
* <ul>
* <li>If no items are left (n == 0), the maximum value is 0.</li>
* <li>If the knapsack's remaining capacity is 0 (w == 0), no more items can
* be included, and the value is 0.</li>
* </ul></p>
*
* <p><b>Recursive Steps:</b>
* <ul>
* <li>If the weight of the n-th item exceeds the current capacity, it is
* excluded from the solution, and the function proceeds with the remaining
* items.</li>
* <li>Otherwise, the function considers two possibilities: include the n-th
* item or exclude it, and returns the maximum value of these two scenarios.</li>
* </ul></p>
*/
static int knapSack(int w, int[] wt, int[] val, int n) {
// Base Case
if (n == 0 || w == 0) {
return 0;
}

// If weight of the nth item is
// more than Knapsack capacity W,
// then this item cannot be included
// in the optimal solution
if (wt[n - 1] > w) {
return knapSack(w, wt, val, n - 1);
} // Return the maximum of two cases:
// (1) nth item included
// (2) not included
else {
return Math.max(val[n - 1] + knapSack(w - wt[n - 1], wt, val, n - 1), knapSack(w, wt, val, n - 1));
} else {
return Math.max(knapSack(w, wt, val, n - 1), val[n - 1] + knapSack(w - wt[n - 1], wt, val, n - 1));
}
}

// Driver code
public static void main(String[] args) {
int[] val = new int[] {60, 100, 120};
int[] wt = new int[] {10, 20, 30};
int w = 50;
int n = val.length;
System.out.println(knapSack(w, wt, val, n));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.thealgorithms.dynamicprogramming;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class BruteForceKnapsackTest {

@Test
void testKnapSackBasicCase() {
int[] val = {60, 100, 120};
int[] wt = {10, 20, 30};
int w = 50;
int n = val.length;

// The expected result for this case is 220 (items 2 and 3 are included)
assertEquals(220, BruteForceKnapsack.knapSack(w, wt, val, n));
}

@Test
void testKnapSackNoItems() {
int[] val = {};
int[] wt = {};
int w = 50;
int n = val.length;

// With no items, the maximum value should be 0
assertEquals(0, BruteForceKnapsack.knapSack(w, wt, val, n));
}

@Test
void testKnapSackZeroCapacity() {
int[] val = {60, 100, 120};
int[] wt = {10, 20, 30};
int w = 0;
int n = val.length;

// With a knapsack of 0 capacity, no items can be included, so the value is 0
assertEquals(0, BruteForceKnapsack.knapSack(w, wt, val, n));
}

@Test
void testKnapSackSingleItemFits() {
int[] val = {100};
int[] wt = {20};
int w = 30;
int n = val.length;

// Only one item, and it fits in the knapsack, so the result is 100
assertEquals(100, BruteForceKnapsack.knapSack(w, wt, val, n));
}

@Test
void testKnapSackSingleItemDoesNotFit() {
int[] val = {100};
int[] wt = {20};
int w = 10;
int n = val.length;

// Single item does not fit in the knapsack, so the result is 0
assertEquals(0, BruteForceKnapsack.knapSack(w, wt, val, n));
}

@Test
void testKnapSackAllItemsFit() {
int[] val = {20, 30, 40};
int[] wt = {1, 2, 3};
int w = 6;
int n = val.length;

// All items fit into the knapsack, so the result is the sum of all values (20 + 30 + 40 = 90)
assertEquals(90, BruteForceKnapsack.knapSack(w, wt, val, n));
}

@Test
void testKnapSackNoneFit() {
int[] val = {100, 200, 300};
int[] wt = {100, 200, 300};
int w = 50;
int n = val.length;

// None of the items fit into the knapsack, so the result is 0
assertEquals(0, BruteForceKnapsack.knapSack(w, wt, val, n));
}

@Test
void testKnapSackSomeItemsFit() {
int[] val = {60, 100, 120};
int[] wt = {10, 20, 30};
int w = 40;
int n = val.length;

// Here, only the 2nd and 1st items should be included for a total value of 160
assertEquals(180, BruteForceKnapsack.knapSack(w, wt, val, n));
}
}