给定一个由整数组成的数组“ arr”,任务是找到子集的数量,以使它们的总和等于零。空子集也应予以考虑。
例子:
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.
一种简单的方法是递归生成所有可能的子集,并计算总和等于0的子集数。此方法的时间复杂度为O(2 ^ n)。
更好的方法是使用动态编程。
让我们假设直到索引i-1为止我们选择的所有元素的总和是S。因此,从索引“ i”开始,我们必须找到总和等于-S的子数组{i,N-1}的子集数。
让我们定义dp [i] [S]。这意味着“ arr”的子数组{i,N-1}的子集的个数之和等于“ -S”。
如果我们处于第i个索引,则有两个选择,即将其包括在总和中或保留它。
因此,所需的递归关系变为
dp[i][s] = dp[i+1][s+arr[i]] + dp[i+1][s]
下面是上述方法的实现:
C++
#include
#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..
7
时间复杂度: O(n * S),其中n是数组中元素的数量,S是所有元素的总和。