From 8bde8a1d8b5c2813e9d3d5ea6524e71930c53d88 Mon Sep 17 00:00:00 2001 From: Manan Solanki Date: Fri, 22 Sep 2023 02:53:12 +0530 Subject: [PATCH 1/8] Enhance Minimum sum partition problem implementation --- .../MinimumSumPartition.java | 89 +++++-------------- .../MinimumSumPartitionTest.java | 38 ++++++++ 2 files changed, 62 insertions(+), 65 deletions(-) create mode 100644 src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java index c15c0186fc62..b81dc862f680 100644 --- a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java +++ b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java @@ -1,8 +1,10 @@ package com.thealgorithms.dynamicprogramming; -// Partition a set into two subsets such that the difference of subset sums is minimum +import java.util.Arrays; /* +Partition a set into two subsets such that the difference of subset sums is minimum + Input: arr[] = {1, 6, 11, 5} Output: 1 Explanation: @@ -17,73 +19,30 @@ */ 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]; - } - } - } + private MinimumSumPartition(){} - // 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; - } - } + public static int minimumSumPartition(final int[] 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 - return getMin(index, sum); - } + //Find the closest sum of subset array that we can achieve which is closest to half of sum of full array + int closestPartitionSum = 0; - /** - * 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; - } - 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); + 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); + } + } } - return min; - } - - /** - * 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; + /* + Difference in sum = Big partition sum - Small partition sum + = ( Total sum - Small partition sum) - Small partition sum + */ + return sum - (2 * closestPartitionSum); } } diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java new file mode 100644 index 000000000000..52e9c8956147 --- /dev/null +++ b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java @@ -0,0 +1,38 @@ +package com.thealgorithms.dynamicprogramming; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class MinimumSumPartitionTest { + + @Test + public void testMinimumSumPartitionWithEvenSum() { + int[] array = {3, 1, 4, 2, 2}; + assertEquals(0, MinimumSumPartition.minimumSumPartition(array)); + } + + @Test + public void testMinimumSumPartitionWithOddSum() { + int[] array = {3, 7, 4, 5, 2}; + assertEquals(1, 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)); + } +} From ea00af05c315617f0dee9c7df8a1996b15c4ead6 Mon Sep 17 00:00:00 2001 From: Manan Solanki Date: Fri, 22 Sep 2023 03:01:18 +0530 Subject: [PATCH 2/8] Linter resolved --- .../dynamicprogramming/MinimumSumPartition.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java index b81dc862f680..6e5227708380 100644 --- a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java +++ b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java @@ -19,14 +19,15 @@ */ public class MinimumSumPartition { - private MinimumSumPartition(){} + private MinimumSumPartition() { + } public static int minimumSumPartition(final int[] 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 - //Find the closest sum of subset array that we can achieve which is closest to half of sum of full array + // 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++) { From 4d6a61aa4af1c51afafa7caf71df967cbdb2145f Mon Sep 17 00:00:00 2001 From: Manan Solanki Date: Fri, 22 Sep 2023 03:04:03 +0530 Subject: [PATCH 3/8] Linter resolved --- .../dynamicprogramming/MinimumSumPartitionTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java index 52e9c8956147..0ddf1c254749 100644 --- a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java +++ b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java @@ -1,9 +1,9 @@ package com.thealgorithms.dynamicprogramming; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + class MinimumSumPartitionTest { @Test From a330058da87e12c89f7b521b04c20fdaf576b0eb Mon Sep 17 00:00:00 2001 From: Manan Solanki Date: Sat, 23 Sep 2023 01:45:25 +0530 Subject: [PATCH 4/8] Code review comments --- .../dynamicprogramming/MinimumSumPartition.java | 11 ++++++----- .../dynamicprogramming/MinimumSumPartitionTest.java | 7 +++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java index 6e5227708380..e9ea063507a9 100644 --- a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java +++ b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java @@ -3,22 +3,23 @@ import java.util.Arrays; /* -Partition a set into two subsets such that the difference of subset sums is minimum +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: arr[] = {1, 6, 11, 5} +Input: array[] = {1, 6, 11, 5} Output: 1 Explanation: Subset1 = {1, 5, 6}, sum of Subset1 = 12 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 final class MinimumSumPartition { private MinimumSumPartition() { } diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java index 0ddf1c254749..a47a0d845930 100644 --- a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java +++ b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java @@ -5,17 +5,16 @@ import org.junit.jupiter.api.Test; class MinimumSumPartitionTest { - @Test public void testMinimumSumPartitionWithEvenSum() { - int[] array = {3, 1, 4, 2, 2}; + int[] array = {1, 6, 11, 4}; assertEquals(0, MinimumSumPartition.minimumSumPartition(array)); } @Test public void testMinimumSumPartitionWithOddSum() { - int[] array = {3, 7, 4, 5, 2}; - assertEquals(1, MinimumSumPartition.minimumSumPartition(array)); + int[] array = {36, 7, 46, 40}; + assertEquals(23, MinimumSumPartition.minimumSumPartition(array)); } @Test From 2017a58e656e1288b2918d83c6748cf47a22837e Mon Sep 17 00:00:00 2001 From: Manan Solanki Date: Sat, 23 Sep 2023 01:46:33 +0530 Subject: [PATCH 5/8] Code review comments --- .../dynamicprogramming/MinimumSumPartition.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java index e9ea063507a9..85d983ad6f18 100644 --- a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java +++ b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java @@ -7,10 +7,10 @@ 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, 5} -Output: 1 +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: array[] = {36, 7, 46, 40} From 5462934c4666dcba1358a34d3de3041a907945bb Mon Sep 17 00:00:00 2001 From: Manan Solanki Date: Sat, 23 Sep 2023 13:25:57 +0530 Subject: [PATCH 6/8] Add validation for non-negative numbers --- .../dynamicprogramming/MinimumSumPartition.java | 7 +++++++ .../dynamicprogramming/MinimumSumPartitionTest.java | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java index 85d983ad6f18..52308c23cf1c 100644 --- a/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java +++ b/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java @@ -23,7 +23,14 @@ public final class MinimumSumPartition { private MinimumSumPartition() { } + 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)."); + } + } + 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 diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java index a47a0d845930..f0a9f50c1b72 100644 --- a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java +++ b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.dynamicprogramming; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; @@ -34,4 +35,10 @@ 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); }); + } } From 576289609f1308231a0b6a14f97974fa46efa141 Mon Sep 17 00:00:00 2001 From: Manan Solanki Date: Sat, 23 Sep 2023 13:29:07 +0530 Subject: [PATCH 7/8] Linter resolved --- .../dynamicprogramming/MinimumSumPartitionTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java index f0a9f50c1b72..0e9489621761 100644 --- a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java +++ b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java @@ -38,7 +38,9 @@ public void testMinimumSumPartitionWithEmptyArray() { @Test public void testMinimumSumPartitionThrowsForNegativeArray() { - int[] array = {4,1,-6,7}; - assertThrows(IllegalArgumentException.class, () -> { MinimumSumPartition.minimumSumPartition(array); }); + int[] array = {4, 1, -6, 7}; + assertThrows(IllegalArgumentException.class, () -> { + MinimumSumPartition.minimumSumPartition(array); + }); } } From ade462b54a933ab5d46fc500f627b78d5c9c0829 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Sat, 23 Sep 2023 10:11:29 +0200 Subject: [PATCH 8/8] style: fix formiatting --- .../dynamicprogramming/MinimumSumPartitionTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java index 0e9489621761..1f14320244ea 100644 --- a/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java +++ b/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java @@ -39,8 +39,6 @@ public void testMinimumSumPartitionWithEmptyArray() { @Test public void testMinimumSumPartitionThrowsForNegativeArray() { int[] array = {4, 1, -6, 7}; - assertThrows(IllegalArgumentException.class, () -> { - MinimumSumPartition.minimumSumPartition(array); - }); + assertThrows(IllegalArgumentException.class, () -> { MinimumSumPartition.minimumSumPartition(array); }); } }