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 : 2
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 : 1
{} 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:
#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 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 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# 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.. |
<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> |
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 :
#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);
} |
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 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))
|
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);
}
} |
// 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)