-
Notifications
You must be signed in to change notification settings - Fork 20k
#4387 Enhance Minimum sum partition problem implementation #4394
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
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8bde8a1
Enhance Minimum sum partition problem implementation
Manan-09 ea00af0
Linter resolved
Manan-09 4d6a61a
Linter resolved
Manan-09 a330058
Code review comments
Manan-09 2017a58
Code review comments
Manan-09 5462934
Add validation for non-negative numbers
Manan-09 5762896
Linter resolved
Manan-09 ade462b
style: fix formiatting
vil02 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
106 changes: 37 additions & 69 deletions
106
src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,57 @@ | ||
package com.thealgorithms.dynamicprogramming; | ||
|
||
// Partition a set into two subsets such that the difference of subset sums is minimum | ||
import java.util.Arrays; | ||
|
||
/* | ||
Input: arr[] = {1, 6, 11, 5} | ||
Output: 1 | ||
Given an array of non-negative integers , partition the array in two subset that | ||
difference in sum of elements for both subset minimum. | ||
Return the minimum difference in sum of these subsets you can achieve. | ||
|
||
Input: array[] = {1, 6, 11, 4} | ||
Output: 0 | ||
Explanation: | ||
Subset1 = {1, 5, 6}, sum of Subset1 = 12 | ||
Subset1 = {1, 4, 6}, sum of Subset1 = 11 | ||
Subset2 = {11}, sum of Subset2 = 11 | ||
|
||
Input: arr[] = {36, 7, 46, 40} | ||
Input: array[] = {36, 7, 46, 40} | ||
Output: 23 | ||
Explanation: | ||
Subset1 = {7, 46} ; sum of Subset1 = 53 | ||
Subset2 = {36, 40} ; sum of Subset2 = 76 | ||
*/ | ||
public class MinimumSumPartition { | ||
|
||
public static int subSet(int[] arr) { | ||
int n = arr.length; | ||
int sum = getSum(arr); | ||
boolean[][] dp = new boolean[n + 1][sum + 1]; | ||
for (int i = 0; i <= n; i++) { | ||
dp[i][0] = true; | ||
} | ||
for (int j = 0; j <= sum; j++) { | ||
dp[0][j] = false; | ||
} | ||
|
||
// fill dp array | ||
for (int i = 1; i <= n; i++) { | ||
for (int j = 1; j <= sum; j++) { | ||
if (arr[i - 1] < j) { | ||
dp[i][j] = dp[i - 1][j - arr[i - 1]] || dp[i - 1][j]; | ||
} else if (arr[i - 1] == j) { | ||
dp[i][j] = true; | ||
} else { | ||
dp[i][j] = dp[i - 1][j]; | ||
} | ||
} | ||
} | ||
|
||
// fill the index array | ||
int[] index = new int[sum]; | ||
int p = 0; | ||
for (int i = 0; i <= sum / 2; i++) { | ||
if (dp[n][i]) { | ||
index[p++] = i; | ||
} | ||
} | ||
|
||
return getMin(index, sum); | ||
public final class MinimumSumPartition { | ||
private MinimumSumPartition() { | ||
} | ||
|
||
/** | ||
* Calculate sum of array elements | ||
* | ||
* @param arr the array | ||
* @return sum of given array | ||
*/ | ||
public static int getSum(int[] arr) { | ||
int sum = 0; | ||
for (int temp : arr) { | ||
sum += temp; | ||
private static void throwIfInvalidInput(final int[] array) { | ||
if (Arrays.stream(array).anyMatch(a -> a < 0)) { | ||
throw new IllegalArgumentException("Input array should not contain negative number(s)."); | ||
} | ||
return sum; | ||
} | ||
|
||
public static int getMin(int[] arr, int sum) { | ||
if (arr.length == 0) { | ||
return 0; | ||
} | ||
int min = Integer.MAX_VALUE; | ||
for (int temp : arr) { | ||
min = Math.min(min, sum - 2 * temp); | ||
} | ||
return min; | ||
} | ||
public static int minimumSumPartition(final int[] array) { | ||
throwIfInvalidInput(array); | ||
int sum = Arrays.stream(array).sum(); | ||
boolean[] dp = new boolean[sum / 2 + 1]; | ||
dp[0] = true; // Base case , don't select any element from array | ||
|
||
/** | ||
* Driver Code | ||
*/ | ||
public static void main(String[] args) { | ||
assert subSet(new int[] {1, 6, 11, 5}) == 1; | ||
assert subSet(new int[] {36, 7, 46, 40}) == 23; | ||
assert subSet(new int[] {1, 2, 3, 9}) == 3; | ||
// Find the closest sum of subset array that we can achieve which is closest to half of sum of full array | ||
int closestPartitionSum = 0; | ||
|
||
for (int i = 0; i < array.length; i++) { | ||
for (int j = sum / 2; j > 0; j--) { | ||
if (array[i] <= j) { | ||
dp[j] = dp[j] || dp[j - array[i]]; | ||
} | ||
if (dp[j]) { | ||
closestPartitionSum = Math.max(closestPartitionSum, j); | ||
} | ||
} | ||
} | ||
/* | ||
Difference in sum = Big partition sum - Small partition sum | ||
= ( Total sum - Small partition sum) - Small partition sum | ||
*/ | ||
return sum - (2 * closestPartitionSum); | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.thealgorithms.dynamicprogramming; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
class MinimumSumPartitionTest { | ||
@Test | ||
public void testMinimumSumPartitionWithEvenSum() { | ||
int[] array = {1, 6, 11, 4}; | ||
assertEquals(0, MinimumSumPartition.minimumSumPartition(array)); | ||
} | ||
|
||
@Test | ||
public void testMinimumSumPartitionWithOddSum() { | ||
int[] array = {36, 7, 46, 40}; | ||
assertEquals(23, MinimumSumPartition.minimumSumPartition(array)); | ||
} | ||
|
||
@Test | ||
public void testMinimumSumPartitionWithSingleElement() { | ||
int[] array = {7}; | ||
assertEquals(7, MinimumSumPartition.minimumSumPartition(array)); | ||
} | ||
|
||
@Test | ||
public void testMinimumSumPartitionWithLargeNumbers() { | ||
int[] array = {100, 200, 300, 400, 500}; | ||
assertEquals(100, MinimumSumPartition.minimumSumPartition(array)); | ||
} | ||
|
||
@Test | ||
public void testMinimumSumPartitionWithEmptyArray() { | ||
int[] array = {}; | ||
assertEquals(0, MinimumSumPartition.minimumSumPartition(array)); | ||
} | ||
|
||
@Test | ||
public void testMinimumSumPartitionThrowsForNegativeArray() { | ||
int[] array = {4, 1, -6, 7}; | ||
assertThrows(IllegalArgumentException.class, () -> { MinimumSumPartition.minimumSumPartition(array); }); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.