Saturday, November 16, 2024
Google search engine
HomeData Modelling & AIPartition a set into two subsets such that the difference of subset...

Partition a set into two subsets such that the difference of subset sums is minimum

Given a set of integers, the task is to divide it into two sets S1 and S2 such that the absolute difference between their sums is minimum. 
If there is a set S with n elements, then if we assume Subset1 has m elements, Subset2 must have n-m elements and the value of abs(sum(Subset1) – sum(Subset2)) should be minimum.

Example: 

Input:  arr[] = {1, 6, 11, 5} 
Output: 1
Explanation:
Subset1 = {1, 5, 6}, sum of Subset1 = 12
Subset2 = {11}, sum of Subset2 = 11
Recommended Practice

This problem is mainly an extension to the Dynamic Programming| Set 18 (Partition Problem). 

Recursive Solution:
The recursive approach is to generate all possible sums from all the values of the array and to check which solution is the most optimal one. To generate sums we either include the i’th item in set 1 or don’t include, i.e., include in set 2.  

C++




// A Recursive C++ program to solve minimum sum partition
// problem.
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the minimum sum
int findMinRec(int arr[], int i, int sumCalculated,
               int sumTotal)
{
    // If we have reached last element.  Sum of one
    // subset is sumCalculated, sum of other subset is
    // sumTotal-sumCalculated.  Return absolute difference
    // of two sums.
    if (i == 0)
        return abs((sumTotal - sumCalculated)
                   - sumCalculated);
 
    // For every item arr[i], we have two choices
    // (1) We do not include it first set
    // (2) We include it in first set
    // We return minimum of two choices
    return min(
        findMinRec(arr, i - 1, sumCalculated + arr[i - 1],
                   sumTotal),
        findMinRec(arr, i - 1, sumCalculated, sumTotal));
}
 
// Returns minimum possible difference between sums
// of two subsets
int findMin(int arr[], int n)
{
    // Compute total sum of elements
    int sumTotal = 0;
    for (int i = 0; i < n; i++)
        sumTotal += arr[i];
 
    // Compute result using recursive function
    return findMinRec(arr, n, 0, sumTotal);
}
 
// Driver program to test above function
int main()
{
    int arr[] = { 3, 1, 4, 2, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "The minimum difference between two sets is "
         << findMin(arr, n);
    return 0;
}


Java




// JAVA code to partition a set into two subsets
// such that the difference of subset sums
// is minimum
import java.util.*;
 
class GFG {
 
    // Function to find the minimum sum
    public static int findMinRec(int arr[], int i,
                                 int sumCalculated,
                                 int sumTotal)
    {
        // If we have reached last element.
        // Sum of one subset is sumCalculated,
        // sum of other subset is sumTotal-
        // sumCalculated.  Return absolute
        // difference of two sums.
        if (i == 0)
            return Math.abs((sumTotal - sumCalculated)
                            - sumCalculated);
 
        // For every item arr[i], we have two choices
        // (1) We do not include it first set
        // (2) We include it in first set
        // We return minimum of two choices
        return Math.min(
            findMinRec(arr, i - 1,
                       sumCalculated + arr[i - 1],
                       sumTotal),
            findMinRec(arr, i - 1, sumCalculated,
                       sumTotal));
    }
 
    // Returns minimum possible difference between
    // sums of two subsets
    public static int findMin(int arr[], int n)
    {
        // Compute total sum of elements
        int sumTotal = 0;
        for (int i = 0; i < n; i++)
            sumTotal += arr[i];
 
        // Compute result using recursive function
        return findMinRec(arr, n, 0, sumTotal);
    }
 
    /* Driver program to test above function */
    public static void main(String[] args)
    {
        int arr[] = { 3, 1, 4, 2, 2, 1 };
        int n = arr.length;
        System.out.print("The minimum difference"
                         + " between two sets is "
                         + findMin(arr, n));
    }
}
 
// This code is contributed by Arnav Kr. Mandal.


Python3




# Python3 program for the
# above approach
 
 
# Function to find the minimum sum
 
 
def findMinRec(arr, i, sumCalculated,
               sumTotal):
 
    # If we have reached last element.
    # Sum of one subset is sumCalculated,
    # sum of other subset is sumTotal-
    # sumCalculated.  Return absolute
    # difference of two sums.
    if (i == 0):
        return abs((sumTotal - sumCalculated) -
                   sumCalculated)
 
    # For every item arr[i], we have two choices
    # (1) We do not include it first set
    # (2) We include it in first set
    # We return minimum of two choices
    return min(findMinRec(arr, i - 1,
                          sumCalculated+arr[i - 1],
                          sumTotal),
               findMinRec(arr, i - 1,
                          sumCalculated, sumTotal))
 
# Returns minimum possible
# difference between sums
# of two subsets
 
 
def findMin(arr,  n):
 
    # Compute total sum
    # of elements
    sumTotal = 0
    for i in range(n):
        sumTotal += arr[i]
 
    # Compute result using
    # recursive function
    return findMinRec(arr, n,
                      0, sumTotal)
 
 
# Driver code
if __name__ == "__main__":
 
    arr = [3, 1, 4, 2, 2, 1]
    n = len(arr)
    print("The minimum difference " +
          "between two sets is ",
          findMin(arr, n))
 
# This code is contributed by Chitranayal


C#




// C# code to partition a set into two subsets
// such that the difference of subset sums
// is minimum
using System;
 
class GFG {
 
    // Function to find the minimum sum
    public static int findMinRec(int[] arr, int i,
                                 int sumCalculated,
                                 int sumTotal)
    {
        // If we have reached last element.
        // Sum of one subset is sumCalculated,
        // sum of other subset is sumTotal-
        // sumCalculated. Return absolute
        // difference of two sums.
        if (i == 0)
            return Math.Abs((sumTotal - sumCalculated)
                            - sumCalculated);
 
        // For every item arr[i], we have two choices
        // (1) We do not include it first set
        // (2) We include it in first set
        // We return minimum of two choices
        return Math.Min(
            findMinRec(arr, i - 1,
                       sumCalculated + arr[i - 1],
                       sumTotal),
            findMinRec(arr, i - 1, sumCalculated,
                       sumTotal));
    }
 
    // Returns minimum possible difference between
    // sums of two subsets
    public static int findMin(int[] arr, int n)
    {
 
        // Compute total sum of elements
        int sumTotal = 0;
        for (int i = 0; i < n; i++)
            sumTotal += arr[i];
 
        // Compute result using recursive function
        return findMinRec(arr, n, 0, sumTotal);
    }
 
    /* Driver program to test above function */
    public static void Main()
    {
        int[] arr = { 3, 1, 4, 2, 2, 1 };
        int n = arr.Length;
        Console.Write("The minimum difference"
                      + " between two sets is "
                      + findMin(arr, n));
    }
}
 
// This code is contributed by nitin mittal.


Javascript




<script>
 
// JAVAscript code to partition a set into two subsets
// such that the difference of subset sums
// is minimum
 
    // Function to find the minimum sum
    function findMinRec(arr, i, sumCalculated, sumTotal)
    {
     
        // If we have reached last element.
        // Sum of one subset is sumCalculated,
        // sum of other subset is sumTotal-
        // sumCalculated.  Return absolute
        // difference of two sums.
        if (i == 0)
            return Math.abs((sumTotal-sumCalculated) -
                                   sumCalculated);
       
       
        // For every item arr[i], we have two choices
        // (1) We do not include it first set
        // (2) We include it in first set
        // We return minimum of two choices
        return Math.min(findMinRec(arr, i - 1, sumCalculated
                                   + arr[i-1], sumTotal),
                                 findMinRec(arr, i-1,
                                  sumCalculated, sumTotal));
    }
     
    // Returns minimum possible difference between
    // sums of two subsets
    function findMin(arr, n)
    {
     
         // Compute total sum of elements
        let sumTotal = 0;
        for (let i = 0; i < n; i++)
            sumTotal += arr[i];
       
        // Compute result using recursive function
        return findMinRec(arr, n, 0, sumTotal);
    }
      
     /* Driver program to test above function */
    let arr=[3, 1, 4, 2, 2, 1];
    let n = arr.length;
    document.write("The minimum difference"+
                        " between two sets is " +
                         findMin(arr, n));
     
    // This code is contributed by rag2127
</script>


Output

The minimum difference between two sets is 1






Time Complexity: 

All the sums can be generated by either 
(1) including that element in set 1.
(2) without including that element in set 1.
So possible combinations are :-
arr[0] (1 or 2) -> 2 values
arr[1] (1 or 2) -> 2 values
.
.
.
arr[n] (2 or 2) -> 2 values
So time complexity will be 2*2*..... *2 (For n times),
that is O(2^n).

Auxiliary Space: O(n), extra space for the recursive function call stack.

An approach using Memoization:
Simplify the process by considering the concepts of taking and not taking elements. There is no requirement to combine two arrays, as you can obtain the difference by subtracting one element from the total sum. The objective is to find the minimum difference.

C++




#include <iostream>
#include <vector>
using namespace std;
 
int f(int idx, int sum, int arr[], int n, int totalSum,
      vector<vector<int> >& dp)
{
    if (idx == n) {
        // One subset sum is 'sum' and the other is
        // 'totalSum - sum'
        return abs((totalSum - sum) - sum);
    }
 
    if (dp[idx][sum] != -1) {
        // If the result for the current index
        // and sum is already computed, return it
        return dp[idx][sum];
    }
 
    // Include the current element in the sum
    int pick
        = f(idx + 1, sum + arr[idx], arr, n, totalSum, dp);
 
    // Exclude the current element from the sum
    int notPick = f(idx + 1, sum, arr, n, totalSum, dp);
 
    // Store the minimum result in the memoization table and
    // return it
    return dp[idx][sum] = min(pick, notPick);
}
 
int findMin(int arr[], int n)
{
    int totalSum = 0;
    for (int i = 0; i < n; i++) {
        totalSum += arr[i];
    }
 
    // Create a memoization table initialized with -1
    vector<vector<int> > dp(n + 1,
                            vector<int>(totalSum + 1, -1));
 
    // Call the recursive function 'f'
    return f(0, 0, arr, n, totalSum, dp);
}
 
int main()
{
    int arr[] = { 3, 1, 4, 2, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Find the minimum difference between two sets
    cout << "The minimum difference between two sets is "
         << findMin(arr, n);
 
    return 0;
}


Java




import java.util.Arrays;
 
class GFG {
 
    public static int f(int idx, int sum, int[] arr, int n,
                        int totalSum, int[][] dp)
    {
        if (idx == n) {
            // One subset sum is 'sum' and the other is
            // 'totalSum - sum'
            return Math.abs((totalSum - sum) - sum);
        }
 
        if (dp[idx][sum] != -1) {
            // If the result for the current index
            // and sum is already computed, return it
            return dp[idx][sum];
        }
 
        // Include the current element in the sum
        int pick = f(idx + 1, sum + arr[idx], arr, n,
                     totalSum, dp);
 
        // Exclude the current element from the sum
        int notPick = f(idx + 1, sum, arr, n, totalSum, dp);
 
        // Store the minimum result in the memoization table
        // and return it
        return dp[idx][sum] = Math.min(pick, notPick);
    }
 
    public static int findMin(int[] arr, int n)
    {
        int totalSum = 0;
        for (int i = 0; i < n; i++) {
            totalSum += arr[i];
        }
 
        // Create a memoization table initialized with -1
        int[][] dp = new int[n + 1][totalSum + 1];
        for (int[] row : dp) {
            Arrays.fill(row, -1);
        }
 
        // Call the recursive function 'f'
        return f(0, 0, arr, n, totalSum, dp);
    }
 
    public static void main(String[] args)
    {
        int[] arr = { 3, 1, 4, 2, 2, 1 };
        int n = arr.length;
 
        // Find the minimum difference between two sets
        System.out.println(
            "The minimum difference between two sets is "
            + findMin(arr, n));
    }
}


Python




def findMin(arr, n):
    totalSum = sum(arr)
 
    # Create a memoization table initialized with -1
    dp = [[-1 for _ in range(totalSum + 1)] for _ in range(n + 1)]
 
    # Recursive function to find the minimum difference between two sets
    def f(idx, sum, arr, n, totalSum, dp):
        if idx == n:
            # One subset sum is 'sum' and the other is 'totalSum - sum'
            return abs((totalSum - sum) - sum)
 
        if dp[idx][sum] != -1:
            # If the result for the current index and
            # sum is already computed, return it
            return dp[idx][sum]
 
        # Include the current element in the sum
        pick = f(idx + 1, sum + arr[idx], arr, n, totalSum, dp)
 
        # Exclude the current element from the sum
        notPick = f(idx + 1, sum, arr, n, totalSum, dp)
 
        # Store the minimum result in the memoization table and return it
        dp[idx][sum] = min(pick, notPick)
        return dp[idx][sum]
 
    # Call the recursive function 'f'
    return f(0, 0, arr, n, totalSum, dp)
 
 
# Main function
if __name__ == "__main__":
    arr = [3, 1, 4, 2, 2, 1]
    n = len(arr)
 
    # Find the minimum difference between two sets
    print("The minimum difference between two sets is", findMin(arr, n))


C#




using System;
 
class MinimumSubsetDifference {
    static int FindMin(int[] arr, int n)
    {
        int totalSum = 0;
        for (int i = 0; i < n; i++) {
            totalSum += arr[i];
        }
 
        // Create a memoization table initialized with -1
        int[][] dp = new int[n + 1][];
        for (int i = 0; i <= n; i++) {
            dp[i] = new int[totalSum + 1];
            for (int j = 0; j <= totalSum; j++) {
                dp[i][j] = -1;
            }
        }
 
        // Call the recursive function 'F'
        return F(0, 0, arr, n, totalSum, dp);
    }
 
    static int F(int idx, int sum, int[] arr, int n,
                 int totalSum, int[][] dp)
    {
        if (idx == n) {
            // One subset sum is 'sum' and the other is
            // 'totalSum - sum'
            return Math.Abs((totalSum - sum) - sum);
        }
 
        if (dp[idx][sum] != -1) {
            // If the result for the current index
            // and sum is already computed, return it
            return dp[idx][sum];
        }
 
        // Include the current element in the sum
        int pick = F(idx + 1, sum + arr[idx], arr, n,
                     totalSum, dp);
 
        // Exclude the current element from the sum
        int notPick = F(idx + 1, sum, arr, n, totalSum, dp);
 
        // Store the minimum result in the memoization table
        // and return it
        return dp[idx][sum] = Math.Min(pick, notPick);
    }
 
    static void Main()
    {
        int[] arr = { 3, 1, 4, 2, 2, 1 };
        int n = arr.Length;
 
        // Find the minimum difference between two sets
        Console.WriteLine(
            "The minimum difference between two sets is "
            + FindMin(arr, n));
    }
}


Javascript




function f(idx, sum, arr, n, totalSum, dp)
{
    if (idx == n) {
        // One subset sum is 'sum' and the other is
        // 'totalSum - sum'
        return Math.abs((totalSum - sum) - sum);
    }
 
    if (dp[idx][sum] != -1) {
        // If the result for the current index
        // and sum is already computed, return it
        return dp[idx][sum];
    }
 
    // Include the current element in the sum
    let pick
        = f(idx + 1, sum + arr[idx], arr, n, totalSum, dp);
 
    // Exclude the current element from the sum
    let notPick = f(idx + 1, sum, arr, n, totalSum, dp);
 
    // Store the minimum result in the memoization table and
    // return it
    return dp[idx][sum] = Math.min(pick, notPick);
}
 
function findMin(arr, n)
{
    let totalSum = 0;
    for (let i = 0; i < n; i++) {
        totalSum += arr[i];
    }
 
    // Create a memoization table initialized with -1
    let dp = new Array(n+1);
     
    for(let i=0; i<n+1; i++)
        dp[i]=new Array(totalSum+1).fill(-1);
 
    // Call the recursive function 'f'
    return f(0, 0, arr, n, totalSum, dp);
}
 
let arr = [ 3, 1, 4, 2, 2, 1 ];
let n = arr.length;
 
// Find the minimum difference between two sets
console.log("The minimum difference between two sets is ", findMin(arr, n));


Output

The minimum difference between two sets is 1






Time Complexity: O(n*sum) where n is the number of elements and sum is the sum of all elements.
Auxiliary Space: O(n*sum)

An approach using dynamic Programming:
The problem can be solved using dynamic programming when the sum of the elements is not too big. We can create a 2D array dp[n+1][sum+1] where n is the number of elements in a given set and sum is the sum of all elements. We can construct the solution in a bottom-up manner.

The task is to divide the set into two parts. 
We will consider the following factors for dividing it.
Let
dp[i][j] = {1 if some subset from 1st to i'th has a sum
equal to j
0 otherwise}

i ranges from {1..n}
j ranges from {0..(sum of all elements)}
So
dp[i][j] will be 1 if
1) The sum j is achieved including i'th item
2) The sum j is achieved excluding i'th item.
Let sum of all the elements be S.
To find Minimum sum difference, we have to find j such
that Min{sum - 2*j : dp[n][j] == 1 }
where j varies from 0 to sum/2
The idea is, sum of S1 is j and it should be closest
to sum/2, i.e., 2*j should be closest to sum (as this will ideally minimize sum-2*j.

Below is the implementation of the above code. 

C++




// A Recursive C++ program to solve minimum sum partition
// problem.
#include <bits/stdc++.h>
using namespace std;
 
// Returns the minimum value of the difference of the two
// sets.
int findMin(int arr[], int n)
{
    // Calculate sum of all elements
    int sum = 0;
    for (int i = 0; i < n; i++)
        sum += arr[i];
 
    // Create an array to store results of subproblems
    bool dp[n + 1][sum + 1];
 
    // Initialize first column as true. 0 sum is possible
    // with all elements.
    for (int i = 0; i <= n; i++)
        dp[i][0] = true;
 
    // Initialize top row, except dp[0][0], as false. With
    // 0 elements, no other sum except 0 is possible
    for (int i = 1; i <= sum; i++)
        dp[0][i] = false;
 
    // Fill the partition table in bottom up manner
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= sum; j++) {
            // If i'th element is excluded
            dp[i][j] = dp[i - 1][j];
 
            // If i'th element is included
            if (arr[i - 1] <= j)
                dp[i][j] |= dp[i - 1][j - arr[i - 1]];
        }
    }
 
    // Initialize difference of two sums.
    int diff = INT_MAX;
 
    // Find the largest j such that dp[n][j]
    // is true where j loops from sum/2 t0 0
    for (int j = sum / 2; j >= 0; j--) {
        // Find the
        if (dp[n][j] == true) {
            diff = sum - 2 * j;
            break;
        }
    }
    return diff;
}
 
// Driver program to test above function
int main()
{
    int arr[] = { 3, 1, 4, 2, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "The minimum difference between 2 sets is "
         << findMin(arr, n);
    return 0;
}


Java




// A Recursive java program to solve
// minimum sum partition problem.
import java.io.*;
 
class GFG {
    // Returns the minimum value of
    // the difference of the two sets.
    static int findMin(int arr[], int n)
    {
        // Calculate sum of all elements
        int sum = 0;
        for (int i = 0; i < n; i++)
            sum += arr[i];
 
        // Create an array to store
        // results of subproblems
        boolean dp[][] = new boolean[n + 1][sum + 1];
 
        // Initialize first column as true.
        // 0 sum is possible  with all elements.
        for (int i = 0; i <= n; i++)
            dp[i][0] = true;
 
        // Initialize top row, except dp[0][0],
        // as false. With 0 elements, no other
        // sum except 0 is possible
        for (int i = 1; i <= sum; i++)
            dp[0][i] = false;
 
        // Fill the partition table
        // in bottom up manner
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= sum; j++) {
                // If i'th element is excluded
                dp[i][j] = dp[i - 1][j];
 
                // If i'th element is included
                if (arr[i - 1] <= j)
                    dp[i][j] |= dp[i - 1][j - arr[i - 1]];
            }
        }
 
        // Initialize difference of two sums.
        int diff = Integer.MAX_VALUE;
 
        // Find the largest j such that dp[n][j]
        // is true where j loops from sum/2 t0 0
        for (int j = sum / 2; j >= 0; j--) {
            // Find the
            if (dp[n][j] == true) {
                diff = sum - 2 * j;
                break;
            }
        }
        return diff;
    }
 
    // Driver program
    public static void main(String[] args)
    {
        int arr[] = { 3, 1, 4, 2, 2, 1 };
        int n = arr.length;
        System.out.println(
            "The minimum difference between 2 sets is "
            + findMin(arr, n));
    }
}
// This code is contributed by vt_m


Python3




# A Recursive Python3 program to solve
# minimum sum partition problem.
import sys
 
# Returns the minimum value of the
# difference of the two sets.
 
 
def findMin(a, n):
 
    su = 0
 
    # Calculate sum of all elements
    su = sum(a)
 
    # Create an 2d list to store
    # results of subproblems
    dp = [[0 for i in range(su + 1)]
          for j in range(n + 1)]
 
    # Initialize first column as true.
    # 0 sum is possible
    # with all elements.
    for i in range(n + 1):
        dp[i][0] = True
 
    # Initialize top row, except dp[0][0],
    # as false. With 0 elements, no other
    # sum except 0 is possible
    for j in range(1, su + 1):
        dp[0][j] = False
 
    # Fill the partition table in
    # bottom up manner
    for i in range(1, n + 1):
        for j in range(1, su + 1):
 
            # If i'th element is excluded
            dp[i][j] = dp[i - 1][j]
 
            # If i'th element is included
            if a[i - 1] <= j:
                dp[i][j] |= dp[i - 1][j - a[i - 1]]
 
    # Initialize difference
    # of two sums.
    diff = sys.maxsize
 
    # Find the largest j such that dp[n][j]
    # is true where j loops from sum/2 t0 0
    for j in range(su // 2, -1, -1):
        if dp[n][j] == True:
            diff = su - (2 * j)
            break
 
    return diff
 
 
# Driver code
a = [3, 1, 4, 2, 2, 1]
n = len(a)
 
print("The minimum difference between "
      "2 sets is ", findMin(a, n))
 
# This code is contributed by Tokir Manva


C#




// A Recursive C# program to solve
// minimum sum partition problem.
using System;
 
class GFG {
 
    // Returns the minimum value of
    // the difference of the two sets.
    static int findMin(int[] arr, int n)
    {
 
        // Calculate sum of all elements
        int sum = 0;
        for (int i = 0; i < n; i++)
            sum += arr[i];
 
        // Create an array to store
        // results of subproblems
        bool[, ] dp = new bool[n + 1, sum + 1];
 
        // Initialize first column as true.
        // 0 sum is possible  with all elements.
        for (int i = 0; i <= n; i++)
            dp[i, 0] = true;
 
        // Initialize top row, except dp[0,0],
        // as false. With 0 elements, no other
        // sum except 0 is possible
        for (int i = 1; i <= sum; i++)
            dp[0, i] = false;
 
        // Fill the partition table
        // in bottom up manner
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= sum; j++) {
 
                // If i'th element is excluded
                dp[i, j] = dp[i - 1, j];
 
                // If i'th element is included
                if (arr[i - 1] <= j)
                    dp[i, j] |= dp[i - 1, j - arr[i - 1]];
            }
        }
 
        // Initialize difference of two sums.
        int diff = int.MaxValue;
 
        // Find the largest j such that dp[n,j]
        // is true where j loops from sum/2 t0 0
        for (int j = sum / 2; j >= 0; j--) {
 
            // Find the
            if (dp[n, j] == true) {
                diff = sum - 2 * j;
                break;
            }
        }
        return diff;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        int[] arr = { 3, 1, 4, 2, 2, 1 };
        int n = arr.Length;
 
        Console.WriteLine("The minimum difference "
                          + "between 2 sets is "
                          + findMin(arr, n));
    }
}
 
// This code is contributed by Rajput-Ji


Javascript




<script>
 
// A Recursive JavaScript program to solve minimum sum partition
// problem.
 
// Returns the minimum value of the difference of the two sets.
function findMin(arr, n)
{
    // Calculate sum of all elements
    let sum = 0;
    for (let i = 0; i < n; i++)
        sum += arr[i];
 
    // Create an array to store results of subproblems
    let dp = new Array(n + 1);
 
    // Initialize first column as true. 0 sum is possible
    // with all elements.
    for (let i = 0; i <= n; i++) {
        dp[i] = new Array(sum + 1);
        for(let j = 0; j <= sum; j++) {
              
            if(j == 0)
                dp[i][j] = true;
        }
    }
 
    // Initialize top row, except dp[0][0], as false. With
    // 0 elements, no other sum except 0 is possible
    for (let i = 1; i <= sum; i++)
        dp[0][i] = false;
 
    // Fill the partition table in bottom up manner
    for (let i=1; i<=n; i++)
    {
        for (let j=1; j<=sum; j++)
        {
            // If i'th element is excluded
            dp[i][j] = dp[i-1][j];
 
            // If i'th element is included
            if (arr[i-1] <= j)
                dp[i][j] |= dp[i-1][j-arr[i-1]];
        }
    }
  
    // Initialize difference of two sums.
    let diff = Number.MAX_VALUE;
      
    // Find the largest j such that dp[n][j]
    // is true where j loops from sum/2 t0 0
    for (let j=Math.floor(sum/2); j>=0; j--)
    {
        // Find the
        if (dp[n][j] == true)
        {
            diff = sum-2*j;
            break;
        }
    }
    return diff;
}
 
// Driver program to test above function
 
    let arr = [ 3, 1, 4, 2, 2, 1 ];
    let n = arr.length;
    document.write( "The minimum difference between 2 sets is "
         + findMin(arr, n));
     
    // This code is contributed by Dharanendra L V.
     
</script>


Output

The minimum difference between 2 sets is 1






Time Complexity = O(n*sum) where n is the number of elements and sum is the sum of all elements.
Auxiliary Space: O(n*sum)

An approach using dynamic Programming with less Space Complexity:
Instead of using 2D array we can solve this problem using 1D array dp[sum/2+1]. Lets say sum of elements of set 1 is x than sum of elements of set 2 will be sm-x (sm is sum of all elements of arr). So we have to minimize abs(sm-2*x).  So for minimizing difference between two sets, we need to know a number that is just less than sum/2 (sum is sum of all elements in array) and can be generated by addition of elements from array. 

C++




#include <iostream>
using namespace std;
 
int minDifference(int arr[], int n)
{
    int sum = 0;
    for (int i = 0; i < n; i++)
        sum += arr[i];
    int y = sum / 2 + 1;
    // dp[i] gives whether is it possible to get i as sum of
    // elements dd is helper variable
    // we use dd to ignoring duplicates
    bool dp[y], dd[y];
 
    // Initialising dp and dd
    for (int i = 0; i < y; i++) {
        dp[i] = dd[i] = false;
    }
 
    // sum = 0 is possible
    dp[0] = true; // let dp array is used for storing
                  // previous values and dd array is used to
                  // store current values
    for (int i = 0; i < n; i++) {
        // updating dd[k] as true if k can be formed using
        // elements from 1 to i+1
        for (int j = 0; j + arr[i] < y; j++) {
            if (dp[j])
                dd[j + arr[i]] = true;
        }
        // updating dd
        for (int j = 0; j < y; j++) {
            if (dd[j])
                dp[j] = true;
            dd[j] = false; // reset dd
        }
    }
    // checking the number from sum/2 to 1 which is possible
    // to get as sum
 
    for (int i = y - 1; i >= 0; i--) {
        if (dp[i])
            return (sum - 2 * i);
        // since i is possible to form then another number
        // is sum-i
        // so mindifference is sum-i-i
    }
}
int main()
{
 
    int arr[] = { 1, 6, 11, 5 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << "The Minimum difference of 2 sets is "
         << minDifference(arr, n) << '\n';
    return 0;
}


Java




import java.util.*;
 
class GFG {
 
    static int minDifference(int arr[], int n)
    {
        int sum = 0;
        for (int i = 0; i < n; i++)
            sum += arr[i];
        int y = sum / 2 + 1;
        // dp[i] gives whether is it possible to get i as
        // sum of elements dd is helper variable we use dd
        // to ignoring duplicates
        boolean dp[] = new boolean[y], dd[]
                                       = new boolean[y];
 
        // Initialising dp and dd
        for (int i = 0; i < y; i++) {
            dp[i] = dd[i] = false;
        }
 
        // sum = 0 is possible
        dp[0] = true; // let dp array is used for storing
                      // previous values and dd array is
                      // used to store current values
        for (int i = 0; i < n; i++) {
            // updating dd[k] as true if k can be formed
            // using elements from 1 to i+1
            for (int j = 0; j + arr[i] < y; j++) {
                if (dp[j])
                    dd[j + arr[i]] = true;
            }
            // updating dd
            for (int j = 0; j < y; j++) {
                if (dd[j])
                    dp[j] = true;
                dd[j] = false; // reset dd
            }
        }
        // checking the number from sum/2 to 1 which is
        // possible to get as sum
 
        for (int i = y - 1; i >= 0; i--) {
            if (dp[i])
                return (sum - 2 * i);
            // since i is possible to form then another
            // number is sum-i so mindifference is sum-i-i
        }
        return 0;
    }
 
    public static void main(String[] args)
    {
 
        int arr[] = { 1, 6, 11, 5 };
        int n = arr.length;
        System.out.print(
            "The Minimum difference of 2 sets is "
            + minDifference(arr, n) + '\n');
    }
}
 
// This code is contributed by umadevi9616


Python3




def minDifference(arr, n):
    sum = 0
    for i in range(n):
        sum += arr[i]
    y = sum // 2 + 1
 
    # dp[i] gives whether is it possible to get i as
    # sum of elements dd is helper variable we use dd
    # to ignoring duplicates
    dp = [False for i in range(y)]
    dd = [False for i in range(y)]
 
    # Initialising dp and dd
 
    # sum = 0 is possible
    dp[0] = True  # let dp array is used for storing
    # previous values and dd array is used to
    # store current values
    for i in range(n):
 
        # updating dd[k] as True if k can be formed
        # using elements from 1 to i+1
        for j in range(y):
            if (j + arr[i] < y and dp[j]):
                dd[j + arr[i]] = True
 
        # updating dd
        for j in range(y):
            if (dd[j]):
                dp[j] = True
            dd[j] = False  # reset dd
 
    # checking the number from sum/2 to 1 which is
    # possible to get as sum
    for i in range(y-1, 0, -1):
        if (dp[i]):
            return (sum - 2 * i)
 
        # since i is possible to form then another
        # number is sum-i so mindifference is sum-i-i
    return 0
 
 
if __name__ == '__main__':
 
    arr = [1, 6, 11, 5]
    n = len(arr)
    print("The Minimum difference of 2 sets is ", minDifference(arr, n))
 
# This code is contributed by umadevi9616


C#




using System;
 
public class GFG {
 
    static int minDifference(int[] arr, int n)
    {
        int sum = 0;
        for (int i = 0; i < n; i++)
            sum += arr[i];
        int y = sum / 2 + 1;
        // dp[i] gives whether is it possible to get i as
        // sum of elements dd is helper variable we use dd
        // to ignoring duplicates
        bool[] dp = new bool[y];
        bool[] dd = new bool[y];
 
        // Initialising dp and dd
        for (int i = 0; i < y; i++) {
            dp[i] = dd[i] = false;
        }
 
        // sum = 0 is possible
        dp[0] = true; // let dp array is used for storing
                      // previous values and dd array is
                      // used to store current values
        for (int i = 0; i < n; i++) {
            // updating dd[k] as true if k can be formed
            // using elements from 1 to i+1
            for (int j = 0; j + arr[i] < y; j++) {
                if (dp[j])
                    dd[j + arr[i]] = true;
            }
            // updating dd
            for (int j = 0; j < y; j++) {
                if (dd[j])
                    dp[j] = true;
                dd[j] = false; // reset dd
            }
        }
        // checking the number from sum/2 to 1 which is
        // possible to get as sum
 
        for (int i = y - 1; i >= 0; i--) {
            if (dp[i])
                return (sum - 2 * i);
            // since i is possible to form then another
            // number is sum-i so mindifference is sum-i-i
        }
        return 0;
    }
 
    public static void Main(String[] args)
    {
 
        int[] arr = { 1, 6, 11, 5 };
        int n = arr.Length;
        Console.Write("The Minimum difference of 2 sets is "
                      + minDifference(arr, n) + '\n');
    }
}
 
// This code contributed by gauravrajput1


Javascript




<script>
    function minDifference(arr , n) {
        var sum = 0;
        for (var i = 0; i < n; i++)
            sum += arr[i];
        var y = parseInt(sum / 2) + 1;
         
        // dp[i] gives whether is it possible to get i as
        // sum of elements dd is helper variable we use dd
        // to ignoring duplicates
        var dp = Array(y).fill(false), dd = Array(y).fill(false);
 
        // Initialising dp and dd
        for (var i = 0; i < y; i++) {
            dp[i] = dd[i] = false;
        }
 
        // sum = 0 is possible
        dp[0] = true;// let dp array is used for storing
                  // previous values and dd array is used to
                  // store current values
        for ( var i = 0; i < n; i++)
        {
         
            // updating dd[k] as true if k can be formed
            // using elements from 1 to i+1
            for (var j = 0; j + arr[i] < y; j++) {
                if (dp[j])
                    dd[j + arr[i]] = true;
            }
             
            // updating dd
            for (var j = 0; j < y; j++) {
                if (dd[j])
                    dp[j] = true;
                dd[j] = false; // reset dd
            }
        }
         
        // checking the number from sum/2 to 1 which is
        // possible to get as sum
        for (var i = y - 1; i >= 0; i--) {
            if (dp[i])
                return (sum - 2 * i);
            // since i is possible to form then another
            // number is sum-i so mindifference is sum-i-i
        }
        return 0;
    }
 
        var arr = [ 1, 6, 11, 5 ];
        var n = arr.length;
        document.write("The Minimum difference of 2 sets is " + minDifference(arr, n) + '\n');
 
// This code is contributed by gauravrajput1
</script>


Output

The Minimum difference of 2 sets is 1






Time Complexity: O(n*sum)
Auxiliary Space: O(sum)

Note that the above solution is in Pseudo Polynomial Time (time complexity is dependent on the numeric value of input).This article is contributed by Abhiraj Smit. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments