Open In App

Number of subsets with zero sum

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given an array ‘arr’ consisting of integers, the task is to find the number of subsets such that their sum is equal to zero. An empty subset should also be considered.

Examples: 

Input : arr[] = {2, 2, -4} 
Output :
All possible subsets: 
{} = 0 
{2} = 2 
{2} = 2 
{-4} = -4 
{2, 2} = 4 
{2, -4} = -2 
{2, -4} = -4 
{2, 2, -4} = 0 
Since, {} and {2, 2, -4} are only possible subsets 
with sum 0, ans will be 2.
Input : arr[] = {1, 1, 1, 1} 
Output :
{} is the only possible subset with 
sum 0, thus ans equals 1.  

One simple approach is to generate all possible subsets recursively and count the number of subsets with a sum equals to 0. The time complexity of this approach will be O(2^n).

A better approach will be using Dynamic programming
Let’s suppose the sum of all the elements we have selected up to index ‘i-1’ is ‘S’. So, starting from index ‘i’, we have to find the number of subsets of the sub-array{i, N-1} with sum equals -S. 
Let’s define dp[i][S]. It means the number of the subset of the subarray{i, N-1} of ‘arr’ with sum equals ‘-S’. 
If we are at ith index, we have two choices, i.e. to include it in the sum or leave it. 
Thus, the required recurrence relation becomes 

dp[i][s] = dp[i+1][s+arr[i]] + dp[i+1][s] 

Below is the implementation of the above approach:  

C++




#include <bits/stdc++.h>
#define maxSum 100
#define arrSize 51
using namespace std;
 
// variable to store
// states of dp
int dp[arrSize][maxSum];
bool visit[arrSize][maxSum];
 
// To find the number of subsets with sum equal to 0
// Since S can be negative, we will maxSum
// to it to make it positive
int SubsetCnt(int i, int s, int arr[], int n)
{
    // Base cases
    if (i == n) {
        if (s == 0)
            return 1;
        else
            return 0;
    }
 
    // Returns the value if a state is already solved
    if (visit[i][s + maxSum])
        return dp[i][s + maxSum];
 
    // If the state is not visited, then continue
    visit[i][s + maxSum] = 1;
 
    // Recurrence relation
    dp[i][s + maxSum] = SubsetCnt(i + 1, s + arr[i], arr, n)
                        + SubsetCnt(i + 1, s, arr, n);
 
    // Returning the value
    return dp[i][s + maxSum];
}
 
// Driver function
int main()
{
    int arr[] = { 2, 2, 2, -4, -4 };
    int n = sizeof(arr) / sizeof(int);
 
    cout << SubsetCnt(0, 0, arr, n);
}


Java




// Java implementation of above approach
class GFG
{
 
    static int maxSum = 100;
    static int arrSize = 51;
 
    // variable to store
    // states of dp
    static int[][] dp = new int[arrSize][maxSum];
    static boolean[][] visit = new boolean[arrSize][maxSum];
 
    // To find the number of subsets with sum equal to 0
    // Since S can be negative, we will maxSum
    // to it to make it positive
    static int SubsetCnt(int i, int s, int arr[], int n)
    {
        // Base cases
        if (i == n)
        {
            if (s == 0)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
 
        // Returns the value if a state is already solved
        if (visit[i][s + arrSize])
        {
            return dp[i][s + arrSize];
        }
 
        // If the state is not visited, then continue
        visit[i][s + arrSize] = true;
 
        // Recurrence relation
        dp[i][s + arrSize] = SubsetCnt(i + 1, s + arr[i], arr, n)
                + SubsetCnt(i + 1, s, arr, n);
 
        // Returning the value
        return dp[i][s + arrSize];
    }
 
    // Driver function
    public static void main(String[] args)
    {
        int arr[] = {2, 2, 2, -4, -4};
        int n = arr.length;
 
        System.out.println(SubsetCnt(0, 0, arr, n));
    }
}
 
/* This code contributed by PrinciRaj1992 */


Python3




# Python3 implementation of above approach
import numpy as np
 
maxSum = 100
arrSize = 51
 
# variable to store
# states of dp
dp = np.zeros((arrSize, maxSum));
visit = np.zeros((arrSize, maxSum));
 
# To find the number of subsets
# with sum equal to 0.
# Since S can be negative,
# we will maxSum to it
# to make it positive
def SubsetCnt(i, s, arr, n) :
     
    # Base cases
    if (i == n) :
        if (s == 0) :
            return 1;
        else :
            return 0;
     
    # Returns the value
    # if a state is already solved
    if (visit[i][s + arrSize]) :
        return dp[i][s + arrSize];
 
    # If the state is not visited,
    # then continue
    visit[i][s + arrSize] = 1;
 
    # Recurrence relation
    dp[i][s + arrSize ] = (SubsetCnt(i + 1, s + arr[i], arr, n) +
                           SubsetCnt(i + 1, s, arr, n));
 
    # Returning the value
    return dp[i][s + arrSize];
 
# Driver Code
if __name__ == "__main__" :
 
    arr = [ 2, 2, 2, -4, -4 ];
    n = len(arr);
 
    print(SubsetCnt(0, 0, arr, n));
 
# This code is contributed by AnkitRai01


C#




// C# implementation of above approach
using System;
 
class GFG
{
 
    static int maxSum = 100;
    static int arrSize = 51;
 
    // variable to store
    // states of dp
    static int [,]dp = new int[arrSize, maxSum];
    static bool [,]visit = new bool[arrSize, maxSum];
 
    // To find the number of subsets with sum equal to 0
    // Since S can be negative, we will maxSum
    // to it to make it positive
    static int SubsetCnt(int i, int s, int []arr, int n)
    {
        // Base cases
        if (i == n)
        {
            if (s == 0)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
 
        // Returns the value if a state is already solved
        if (visit[i, s + arrSize])
        {
            return dp[i, s + arrSize];
        }
 
        // If the state is not visited, then continue
        visit[i, s + arrSize] = true;
 
        // Recurrence relation
        dp[i, s + arrSize] = SubsetCnt(i + 1, s + arr[i], arr, n)
                + SubsetCnt(i + 1, s, arr, n);
 
        // Returning the value
        return dp[i,s + arrSize];
    }
 
    // Driver code
    public static void Main()
    {
        int []arr = {2, 2, 2, -4, -4};
        int n = arr.Length;
 
        Console.WriteLine(SubsetCnt(0, 0, arr, n));
    }
}
 
// This code contributed by anuj_67..


Javascript




<script>
 
var maxSum = 100
var arrSize = 51
 
// variable to store
// states of dp
var dp = Array.from(Array(arrSize), ()=> Array(maxSum));
var visit = Array.from(Array(arrSize), ()=> Array(maxSum));
 
// To find the number of subsets with sum equal to 0
// Since S can be negative, we will maxSum
// to it to make it positive
function SubsetCnt(i, s, arr, n)
{
    // Base cases
    if (i == n) {
        if (s == 0)
            return 1;
        else
            return 0;
    }
 
    // Returns the value if a state is already solved
    if (visit[i][s + maxSum])
        return dp[i][s + maxSum];
 
    // If the state is not visited, then continue
    visit[i][s + maxSum] = 1;
 
    // Recurrence relation
    dp[i][s + maxSum] = SubsetCnt(i + 1, s + arr[i], arr, n)
                        + SubsetCnt(i + 1, s, arr, n);
 
    // Returning the value
    return dp[i][s + maxSum];
}
 
// Driver function
var arr = [2, 2, 2, -4, -4];
var n = arr.length;
document.write( SubsetCnt(0, 0, arr, n));
 
</script>


Output

7



Time Complexity: O(N*S), where N is the number of elements in the array, and S is the sum of all the elements.
Auxiliary Space: O(N*S)

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

  • Create a DP to store the solution of the subproblems.
  • Initialize the DP with base cases.
  • Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
  • Return the final solution stored in return dp[n][maxSum]

Implementation :

C++




#include <bits/stdc++.h>
#define maxSum 100
#define arrSize 51
using namespace std;
 
// To find the number of subsets with sum equal to 0
// Since S can be negative, we will maxSum
// to it to make it positive
int SubsetCnt(int arr[], int n)
{
    int dp[n + 1][maxSum * 2 + 1];
 
    // Initializing first column with 1
    for (int i = 0; i <= n; i++) {
        dp[i][maxSum] = 1;
    }
 
    // Initializing rest of the matrix with 0
    for (int i = 1; i <= maxSum * 2; i++) {
        dp[0][i] = 0;
    }
 
    // Filling up the dp matrix
    for (int i = 1; i <= n; i++) {
        for (int j = -maxSum; j <= maxSum; j++) {
            int val = arr[i - 1];
 
            if (j - val + maxSum >= 0
                && j - val + maxSum <= maxSum * 2) {
                dp[i][j + maxSum]
                    += dp[i - 1][j - val + maxSum];
            }
 
            if (j + maxSum >= 0
                && j + maxSum <= maxSum * 2) {
                dp[i][j + maxSum] += dp[i - 1][j + maxSum];
            }
        }
    }
 
    // return final answer
    return dp[n][maxSum];
}
 
// Driver code
 
int main()
{
    int arr[] = { 2, 2, 2, -4, -4 };
    int n = sizeof(arr) / sizeof(int);
 
    // function call
    cout << SubsetCnt(arr, n);
}


Java




import java.util.*;
 
public class Main {
    static int maxSum = 100;
    static int arrSize = 51;
 
    // To find the number of subsets with sum equal to 0
    // Since S can be negative, we will maxSum
    // to it to make it positive
    static int SubsetCnt(int arr[], int n) {
        int dp[][] = new int[n + 1][maxSum * 2 + 1];
 
        // Initializing first column with 1
        for (int i = 0; i <= n; i++) {
            dp[i][maxSum] = 1;
        }
 
        // Initializing rest of the matrix with 0
        for (int i = 1; i <= maxSum * 2; i++) {
            dp[0][i] = 0;
        }
 
        // Filling up the dp matrix
        for (int i = 1; i <= n; i++) {
            for (int j = -maxSum; j <= maxSum; j++) {
                int val = arr[i - 1];
 
                if (j - val + maxSum >= 0 && j - val + maxSum <= maxSum * 2) {
                    dp[i][j + maxSum] += dp[i - 1][j - val + maxSum];
                }
 
                if (j + maxSum >= 0 && j + maxSum <= maxSum * 2) {
                    dp[i][j + maxSum] += dp[i - 1][j + maxSum];
                }
            }
        }
 
        // return final answer
        return dp[n][maxSum];
    }
 
    // Driver code
    public static void main(String[] args) {
        int arr[] = { 2, 2, 2, -4, -4 };
        int n = arr.length;
 
        // function call
        System.out.println(SubsetCnt(arr, n));
    }
}


Python




# Python implementation of the approach
MAX_SUM = 100
ARR_SIZE = 51
 
# To find the number of subsets with sum equal to 0
# Since S can be negative, we will add MAX_SUM
# to it to make it positive
 
 
def SubsetCnt(arr, n):
    dp = [[0 for i in range(MAX_SUM*2+1)] for j in range(n+1)]
 
    # Initializing first column with 1
    for i in range(n+1):
        dp[i][MAX_SUM] = 1
 
    # Initializing rest of the matrix with 0
    for i in range(1, MAX_SUM*2+1):
        dp[0][i] = 0
 
    # Filling up the dp matrix
    for i in range(1, n+1):
        for j in range(-MAX_SUM, MAX_SUM+1):
            val = arr[i-1]
 
            if j-val+MAX_SUM >= 0 and j-val+MAX_SUM <= MAX_SUM*2:
                dp[i][j+MAX_SUM] += dp[i-1][j-val+MAX_SUM]
 
            if j+MAX_SUM >= 0 and j+MAX_SUM <= MAX_SUM*2:
                dp[i][j+MAX_SUM] += dp[i-1][j+MAX_SUM]
 
    # return final answer
    return dp[n][MAX_SUM]
 
 
# Driver code
if __name__ == '__main__':
    arr = [2, 2, 2, -4, -4]
    n = len(arr)
 
    # function call
    print(SubsetCnt(arr, n))


C#




using System;
 
class Program
{
    // Function to find the number of subsets with a sum equal to 0
    static int SubsetCnt(int[] arr, int n)
    {
        int maxSum = 100; // Maximum possible sum
        int[][] dp = new int[n + 1][];
         
        // Create a 2D array 'dp' to store intermediate results
        for (int i = 0; i <= n; i++)
        {
            dp[i] = new int[maxSum * 2 + 1];
        }
 
        // Initializing the first column with 1, representing an empty subset
        for (int i = 0; i <= n; i++)
        {
            dp[i][maxSum] = 1;
        }
 
        // Initializing the rest of the matrix with 0
        for (int i = 1; i <= maxSum * 2; i++)
        {
            dp[0][i] = 0;
        }
 
        // Filling up the dp matrix
        for (int i = 1; i <= n; i++)
        {
            for (int j = -maxSum; j <= maxSum; j++)
            {
                int val = arr[i - 1];
 
                if (j - val + maxSum >= 0 && j - val + maxSum <= maxSum * 2)
                {
                    dp[i][j + maxSum] += dp[i - 1][j - val + maxSum];
                }
 
                if (j + maxSum >= 0 && j + maxSum <= maxSum * 2)
                {
                    dp[i][j + maxSum] += dp[i - 1][j + maxSum];
                }
            }
        }
 
        // Return the final answer (number of subsets with a sum equal to 0)
        return dp[n][maxSum];
    }
 
    // Driver code
    static void Main()
    {
        int[] arr = { 2, 2, 2, -4, -4 };
        int n = arr.Length;
 
        // Function call to find the number of subsets
        int result = SubsetCnt(arr, n);
 
        // Display the result
        Console.WriteLine(result);
    }
}


Javascript




// Function to find the number of subsets with a sum equal to 0
function subsetCnt(arr) {
    const maxSum = 100; // Maximum possible sum
    const n = arr.length;
 
    // Create a 2D array 'dp' to store intermediate results
    const dp = new Array(n + 1);
    for (let i = 0; i <= n; i++) {
        dp[i] = new Array(2 * maxSum + 1).fill(0);
    }
 
    // Initializing the first column with 1, representing an empty subset
    for (let i = 0; i <= n; i++) {
        dp[i][maxSum] = 1;
    }
 
    // Initializing the rest of the matrix with 0
    for (let i = 1; i <= 2 * maxSum; i++) {
        dp[0][i] = 0;
    }
 
    // Filling up the dp matrix
    for (let i = 1; i <= n; i++) {
        for (let j = -maxSum; j <= maxSum; j++) {
            const val = arr[i - 1];
 
            if (j - val + maxSum >= 0 && j - val + maxSum <= 2 * maxSum) {
                dp[i][j + maxSum] += dp[i - 1][j - val + maxSum];
            }
 
            if (j + maxSum >= 0 && j + maxSum <= 2 * maxSum) {
                dp[i][j + maxSum] += dp[i - 1][j + maxSum];
            }
        }
    }
 
    // Return the final answer (number of subsets with a sum equal to 0)
    return dp[n][maxSum];
}
 
// Driver code
const arr = [2, 2, 2, -4, -4];
const n = arr.length;
 
// Function call to find the number of subsets
const result = subsetCnt(arr);
 
// Display the result
console.log(result);


Output

7

Time Complexity: O(N*S), where N is the number of elements in the array, and S is the sum of all the elements.
Auxiliary Space: O(N*S)



Last Updated : 12 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads