📜  总和等于X的子集数

📅  最后修改于: 2021-05-07 01:41:27             🧑  作者: Mango

给定长度为N的数组arr []和整数X ,任务是找到总和等于X的子集数。
例子:

方法:一种简单的方法是通过生成所有可能的子集然后检查该子集是否具有所需的总和来解决此问题。这种方法将具有指数的时间复杂度。但是,对于较小的X和数组元素值,可以使用动态编程解决此问题。
我们先来看一下递归关系。

现在让我们了解DP的状态。在这里, dp [i] [C]存储子数组arr [i…N-1]的子集数,以使它们的总和等于C。
因此,重复是非常琐碎的,因为只有两个选择,即要么考虑子集中的i元素,要么不考虑。
下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
#define maxN 20
#define maxSum 50
#define minSum 50
#define base 50
 
// To store the states of DP
int dp[maxN][maxSum + minSum];
bool v[maxN][maxSum + minSum];
 
// Function to return the required count
int findCnt(int* arr, int i, int required_sum, int n)
{
    // Base case
    if (i == n) {
        if (required_sum == 0)
            return 1;
        else
            return 0;
    }
 
    // If the state has been solved before
    // return the value of the state
    if (v[i][required_sum + base])
        return dp[i][required_sum + base];
 
    // Setting the state as solved
    v[i][required_sum + base] = 1;
 
    // Recurrence relation
    dp[i][required_sum + base]
        = findCnt(arr, i + 1, required_sum, n)
          + findCnt(arr, i + 1, required_sum - arr[i], n);
    return dp[i][required_sum + base];
}
 
// Driver code
int main()
{
    int arr[] = { 3, 3, 3, 3 };
    int n = sizeof(arr) / sizeof(int);
    int x = 6;
 
    cout << findCnt(arr, 0, x, n);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
 
class GFG
{
static int maxN = 20;
static int maxSum = 50;
static int minSum = 50;
static int base = 50;
 
// To store the states of DP
static int [][]dp = new int[maxN][maxSum + minSum];
static boolean [][]v = new boolean[maxN][maxSum + minSum];
 
// Function to return the required count
static int findCnt(int []arr, int i,
                   int required_sum, int n)
{
    // Base case
    if (i == n)
    {
        if (required_sum == 0)
            return 1;
        else
            return 0;
    }
 
    // If the state has been solved before
    // return the value of the state
    if (v[i][required_sum + base])
        return dp[i][required_sum + base];
 
    // Setting the state as solved
    v[i][required_sum + base] = true;
 
    // Recurrence relation
    dp[i][required_sum + base] =
          findCnt(arr, i + 1, required_sum, n) +
          findCnt(arr, i + 1, required_sum - arr[i], n);
    return dp[i][required_sum + base];
}
 
// Driver code
public static void main(String []args)
{
    int arr[] = { 3, 3, 3, 3 };
    int n = arr.length;
    int x = 6;
 
    System.out.println(findCnt(arr, 0, x, n));
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 implementation of the approach
import numpy as np
 
maxN = 20
maxSum = 50
minSum = 50
base = 50
 
# To store the states of DP
dp = np.zeros((maxN, maxSum + minSum));
v = np.zeros((maxN, maxSum + minSum));
 
# Function to return the required count
def findCnt(arr, i, required_sum, n) :
 
    # Base case
    if (i == n) :
        if (required_sum == 0) :
            return 1;
        else :
            return 0;
 
    # If the state has been solved before
    # return the value of the state
    if (v[i][required_sum + base]) :
        return dp[i][required_sum + base];
 
    # Setting the state as solved
    v[i][required_sum + base] = 1;
 
    # Recurrence relation
    dp[i][required_sum + base] = findCnt(arr, i + 1,
                                         required_sum, n) + \
                                 findCnt(arr, i + 1,
                                         required_sum - arr[i], n);
     
    return dp[i][required_sum + base];
 
# Driver code
if __name__ == "__main__" :
 
    arr = [ 3, 3, 3, 3 ];
    n = len(arr);
    x = 6;
 
    print(findCnt(arr, 0, x, n));
 
# This code is contributed by AnkitRai01


C#
// C# implementation of the approach
using System;
     
class GFG
{
 
static int maxN = 20;
static int maxSum = 50;
static int minSum = 50;
static int Base = 50;
 
// To store the states of DP
static int [,]dp = new int[maxN, maxSum + minSum];
static Boolean [,]v = new Boolean[maxN, maxSum + minSum];
 
// Function to return the required count
static int findCnt(int []arr, int i,
                   int required_sum, int n)
{
    // Base case
    if (i == n)
    {
        if (required_sum == 0)
            return 1;
        else
            return 0;
    }
 
    // If the state has been solved before
    // return the value of the state
    if (v[i, required_sum + Base])
        return dp[i, required_sum + Base];
 
    // Setting the state as solved
    v[i, required_sum + Base] = true;
 
    // Recurrence relation
    dp[i, required_sum + Base] =
          findCnt(arr, i + 1, required_sum, n) +
          findCnt(arr, i + 1, required_sum - arr[i], n);
    return dp[i,required_sum + Base];
}
 
// Driver code
public static void Main(String []args)
{
    int []arr = { 3, 3, 3, 3 };
    int n = arr.Length;
    int x = 6;
 
    Console.WriteLine(findCnt(arr, 0, x, n));
}
}
 
// This code is contributed by 29AjayKumar


C++
#include 
using namespace std;
 
int subsetSum(int a[], int n, int sum)
{
    // Initializing the matrix
    int tab[n + 1][sum + 1];
  // Initializing the first value of matrix
    tab[0][0] = 1;
    for (int i = 1; i <= sum; i++)
        tab[0][i] = 0;
    for (int i = 1; i <= n; i++)
        tab[i][0] = 1;
 
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= sum; j++)
        {
          // if the value is greater than the sum
            if (a[i - 1] > j)
                tab[i][j] = tab[i - 1][j];
            else
            {
                tab[i][j] = tab[i - 1][j] + tab[i - 1][j - a[i - 1]];
            }
        }
    }
 
 
    return tab[n][sum];
}
 
int main()
{
    int n = 4;
    int a[] = {3,3,3,3};
    int sum = 6;
 
    cout << (subsetSum(a, n, sum));
}


输出
6

方法2:使用制表法:

In this method we use a 2D array of size (arr.size() + 1) * (target + 1) of type integer.
Initialization of Matrix:
mat[0][0] = 1 because If the size of sum is 
if (A[i] > j)
DP[i][j] = DP[i-1][j]
else 
DP[i][j] = DP[i-1][j] + DP[i-1][j-A[i]]

这意味着如果当前元素的值大于“当前总和值”,我们将复制先前情况的答案

如果当前的总和值大于’ith’元素,我们将查看先前的任何状态是否已经经历了sum =’j’,并且先前的任何状态都经历了值’j – A [i]’可以解决我们的宗旨

C++

#include 
using namespace std;
 
int subsetSum(int a[], int n, int sum)
{
    // Initializing the matrix
    int tab[n + 1][sum + 1];
  // Initializing the first value of matrix
    tab[0][0] = 1;
    for (int i = 1; i <= sum; i++)
        tab[0][i] = 0;
    for (int i = 1; i <= n; i++)
        tab[i][0] = 1;
 
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= sum; j++)
        {
          // if the value is greater than the sum
            if (a[i - 1] > j)
                tab[i][j] = tab[i - 1][j];
            else
            {
                tab[i][j] = tab[i - 1][j] + tab[i - 1][j - a[i - 1]];
            }
        }
    }
 
 
    return tab[n][sum];
}
 
int main()
{
    int n = 4;
    int a[] = {3,3,3,3};
    int sum = 6;
 
    cout << (subsetSum(a, n, sum));
}
输出
6

时间复杂度: O(sum * n),其中,总和是“目标总和”,而“ n”是数组的大小。

辅助空间:作为二维数组的大小,O(sum * n)为sum * n。