📌  相关文章
📜  计数将数组拆分为一对子集的方法,它们的总和等于 K

📅  最后修改于: 2021-09-17 06:47:35             🧑  作者: Mango

给定一个由N 个整数和一个整数K组成的数组arr[] ,任务是找到将数组拆分为一对子集的方法数,使得它们的总和之间的差为K

例子:

朴素的方法:解决给定问题的简单方法是生成所有可能的子集并将每个子集的总和存储在一个数组中,例如subset[] 。然后,检查数组子集 [] 中是否存在差为K 的任何对。检查所有对后,打印这些对的总数作为结果。
时间复杂度: O(2 N )
辅助空间: O(2 N )

有效的方法:可以使用以下观察来优化上述方法。

设第一个和第二个子集的总和分别为S1S2 ,数组元素的总和为Y

因此,对于具有总和S1S2 的一对子集,等式 (3) 必须成立,即,该子集的元素之和必须等于(K + Y)/2 。现在,问题简化为计算给定总和的子集数量。这个问题可以用动态规划解决,其递推关系如下:

这里, dp[i][C]存储子数组 arr[i … N – 1]的子集数量,这样它们的总和等于C
因此,递归是非常微不足道的,因为只有两种选择,即,要么考虑子集中的i数组元素,要么不考虑。

下面是上述方法的实现:

C++
// C++ program for the above 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 find count of subsets
// with a given sum
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 an already computed
    // subproblem occurs
    if (v[i][required_sum + base])
        return dp[i][required_sum + base];
 
    // Set 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];
}
 
// Function to count ways to split array into
// pair of subsets with difference K
void countSubsets(int* arr, int K,
                  int n)
{
 
    // Store the total sum of
    // element of the array
    int sum = 0;
 
    // Traverse the array
    for (int i = 0; i < n; i++) {
 
        // Calculate sum of array elements
        sum += arr[i];
    }
 
    // Store the required sum
    int S1 = (sum + K) / 2;
 
    // Print the number of subsets
    // with sum equal to S1
    cout << findCnt(arr, 0, S1, n);
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 1, 2, 3 };
    int N = sizeof(arr) / sizeof(int);
    int K = 1;
 
    // Function Call
    countSubsets(arr, K, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
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 find count of subsets
  // with a given sum
  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 an already computed
    // subproblem occurs
    if (v[i][required_sum + Base])
      return dp[i][required_sum + Base];
 
    // Set 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];
  }  
 
  // Function to count ways to split array into
  // pair of subsets with difference K
  static void countSubsets(int[] arr, int K,
                           int n)
  {
    // Store the total sum of
    // element of the array
    int sum = 0;
 
    // Traverse the array
    for (int i = 0; i < n; i++)
    {
 
      // Calculate sum of array elements
      sum += arr[i];
    }
 
    // Store the required sum
    int S1 = (sum + K) / 2;
 
    // Print the number of subsets
    // with sum equal to S1
    System.out.print(findCnt(arr, 0, S1, n));
  } 
 
 
  // Driver Code
  public static void main(String[] args)
  {
    int[] arr = { 1, 1, 2, 3 };
    int N = arr.length;
    int K = 1;
 
    // Function Call
    countSubsets(arr, K, N);
  }
}
 
// This code is contributed by sanjoy_62.


Python3
# Python program for the above approach
maxN = 20;
maxSum = 50;
minSum = 50;
Base = 50;
 
# To store the states of DP
dp = [[0 for i in range(maxSum + minSum)] for j in range(maxN)];
v = [[False for i in range(maxSum + minSum)] for j in range(maxN)];
 
# Function to find count of subsets
# with a given sum
def findCnt(arr, i, required_sum, n):
   
    # Base case
    if (i == n):
        if (required_sum == 0):
            return 1;
        else:
            return 0;
 
    # If an already computed
    # subproblem occurs
    if (v[i][required_sum + Base]):
        return dp[i][required_sum + Base];
 
    # Set 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];
 
# Function to count ways to split array into
# pair of subsets with difference K
def countSubsets(arr, K, n):
   
    # Store the total sum of
    # element of the array
    sum = 0;
 
    # Traverse the array
    for i in range(n):
       
        # Calculate sum of array elements
        sum += arr[i];
 
    # Store the required sum
    S1 = (sum + K) // 2;
 
    # Prthe number of subsets
    # with sum equal to S1
    print(findCnt(arr, 0, S1, n));
 
# Driver Code
if __name__ == '__main__':
    arr = [1, 1, 2, 3];
    N = len(arr);
    K = 1;
 
    # Function Call
    countSubsets(arr, K, N);
 
    # This code is contributed by shikhasingrajput


C#
// C# program for the above 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 bool[,] v = new bool[maxN, maxSum + minSum];
       
    // Function to find count of subsets
    // with a given sum
    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 an already computed
        // subproblem occurs
        if (v[i, required_sum + Base])
            return dp[i, required_sum + Base];
       
        // Set 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];
    }
       
    // Function to count ways to split array into
    // pair of subsets with difference K
    static void countSubsets(int[] arr, int K,
                      int n)
    {
       
        // Store the total sum of
        // element of the array
        int sum = 0;
       
        // Traverse the array
        for (int i = 0; i < n; i++)
        {
       
            // Calculate sum of array elements
            sum += arr[i];
        }
       
        // Store the required sum
        int S1 = (sum + K) / 2;
       
        // Print the number of subsets
        // with sum equal to S1
        Console.Write(findCnt(arr, 0, S1, n));
    }  
 
  // Driver code
  static void Main()
  {
    int[] arr = { 1, 1, 2, 3 };
    int N = arr.Length;
    int K = 1;
   
    // Function Call
    countSubsets(arr, K, N);
  }
}
 
// This code is contributed by divyeshrabadiya07.


Javascript


输出:
3

时间复杂度: O(N*K)
辅助空间: O(N*K)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程