Skip to content

Commit 8803b1e

Browse files
Manan-09vil02
andauthored
TheAlgorithms#4387 Enhance Minimum sum partition problem implementation (TheAlgorithms#4394)
* Enhance Minimum sum partition problem implementation * Linter resolved * Linter resolved * Code review comments * Code review comments * Add validation for non-negative numbers * Linter resolved * style: fix formiatting --------- Co-authored-by: Piotr Idzik <[email protected]>
1 parent fbe348b commit 8803b1e

File tree

2 files changed

+81
-69
lines changed

2 files changed

+81
-69
lines changed
Lines changed: 37 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,57 @@
11
package com.thealgorithms.dynamicprogramming;
22

3-
// Partition a set into two subsets such that the difference of subset sums is minimum
3+
import java.util.Arrays;
44

55
/*
6-
Input: arr[] = {1, 6, 11, 5}
7-
Output: 1
6+
Given an array of non-negative integers , partition the array in two subset that
7+
difference in sum of elements for both subset minimum.
8+
Return the minimum difference in sum of these subsets you can achieve.
9+
10+
Input: array[] = {1, 6, 11, 4}
11+
Output: 0
812
Explanation:
9-
Subset1 = {1, 5, 6}, sum of Subset1 = 12
13+
Subset1 = {1, 4, 6}, sum of Subset1 = 11
1014
Subset2 = {11}, sum of Subset2 = 11
1115
12-
Input: arr[] = {36, 7, 46, 40}
16+
Input: array[] = {36, 7, 46, 40}
1317
Output: 23
1418
Explanation:
1519
Subset1 = {7, 46} ; sum of Subset1 = 53
1620
Subset2 = {36, 40} ; sum of Subset2 = 76
1721
*/
18-
public class MinimumSumPartition {
19-
20-
public static int subSet(int[] arr) {
21-
int n = arr.length;
22-
int sum = getSum(arr);
23-
boolean[][] dp = new boolean[n + 1][sum + 1];
24-
for (int i = 0; i <= n; i++) {
25-
dp[i][0] = true;
26-
}
27-
for (int j = 0; j <= sum; j++) {
28-
dp[0][j] = false;
29-
}
30-
31-
// fill dp array
32-
for (int i = 1; i <= n; i++) {
33-
for (int j = 1; j <= sum; j++) {
34-
if (arr[i - 1] < j) {
35-
dp[i][j] = dp[i - 1][j - arr[i - 1]] || dp[i - 1][j];
36-
} else if (arr[i - 1] == j) {
37-
dp[i][j] = true;
38-
} else {
39-
dp[i][j] = dp[i - 1][j];
40-
}
41-
}
42-
}
43-
44-
// fill the index array
45-
int[] index = new int[sum];
46-
int p = 0;
47-
for (int i = 0; i <= sum / 2; i++) {
48-
if (dp[n][i]) {
49-
index[p++] = i;
50-
}
51-
}
52-
53-
return getMin(index, sum);
22+
public final class MinimumSumPartition {
23+
private MinimumSumPartition() {
5424
}
5525

56-
/**
57-
* Calculate sum of array elements
58-
*
59-
* @param arr the array
60-
* @return sum of given array
61-
*/
62-
public static int getSum(int[] arr) {
63-
int sum = 0;
64-
for (int temp : arr) {
65-
sum += temp;
26+
private static void throwIfInvalidInput(final int[] array) {
27+
if (Arrays.stream(array).anyMatch(a -> a < 0)) {
28+
throw new IllegalArgumentException("Input array should not contain negative number(s).");
6629
}
67-
return sum;
6830
}
6931

70-
public static int getMin(int[] arr, int sum) {
71-
if (arr.length == 0) {
72-
return 0;
73-
}
74-
int min = Integer.MAX_VALUE;
75-
for (int temp : arr) {
76-
min = Math.min(min, sum - 2 * temp);
77-
}
78-
return min;
79-
}
32+
public static int minimumSumPartition(final int[] array) {
33+
throwIfInvalidInput(array);
34+
int sum = Arrays.stream(array).sum();
35+
boolean[] dp = new boolean[sum / 2 + 1];
36+
dp[0] = true; // Base case , don't select any element from array
8037

81-
/**
82-
* Driver Code
83-
*/
84-
public static void main(String[] args) {
85-
assert subSet(new int[] {1, 6, 11, 5}) == 1;
86-
assert subSet(new int[] {36, 7, 46, 40}) == 23;
87-
assert subSet(new int[] {1, 2, 3, 9}) == 3;
38+
// Find the closest sum of subset array that we can achieve which is closest to half of sum of full array
39+
int closestPartitionSum = 0;
40+
41+
for (int i = 0; i < array.length; i++) {
42+
for (int j = sum / 2; j > 0; j--) {
43+
if (array[i] <= j) {
44+
dp[j] = dp[j] || dp[j - array[i]];
45+
}
46+
if (dp[j]) {
47+
closestPartitionSum = Math.max(closestPartitionSum, j);
48+
}
49+
}
50+
}
51+
/*
52+
Difference in sum = Big partition sum - Small partition sum
53+
= ( Total sum - Small partition sum) - Small partition sum
54+
*/
55+
return sum - (2 * closestPartitionSum);
8856
}
8957
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
class MinimumSumPartitionTest {
9+
@Test
10+
public void testMinimumSumPartitionWithEvenSum() {
11+
int[] array = {1, 6, 11, 4};
12+
assertEquals(0, MinimumSumPartition.minimumSumPartition(array));
13+
}
14+
15+
@Test
16+
public void testMinimumSumPartitionWithOddSum() {
17+
int[] array = {36, 7, 46, 40};
18+
assertEquals(23, MinimumSumPartition.minimumSumPartition(array));
19+
}
20+
21+
@Test
22+
public void testMinimumSumPartitionWithSingleElement() {
23+
int[] array = {7};
24+
assertEquals(7, MinimumSumPartition.minimumSumPartition(array));
25+
}
26+
27+
@Test
28+
public void testMinimumSumPartitionWithLargeNumbers() {
29+
int[] array = {100, 200, 300, 400, 500};
30+
assertEquals(100, MinimumSumPartition.minimumSumPartition(array));
31+
}
32+
33+
@Test
34+
public void testMinimumSumPartitionWithEmptyArray() {
35+
int[] array = {};
36+
assertEquals(0, MinimumSumPartition.minimumSumPartition(array));
37+
}
38+
39+
@Test
40+
public void testMinimumSumPartitionThrowsForNegativeArray() {
41+
int[] array = {4, 1, -6, 7};
42+
assertThrows(IllegalArgumentException.class, () -> { MinimumSumPartition.minimumSumPartition(array); });
43+
}
44+
}

0 commit comments

Comments
 (0)