给定一个由n个整数和一个整数K组成的数组arr [] ,任务是找到将数组拆分为成对的子集的方式数,以使它们的和之间的差为K。
例子:
Input: arr[] = {1, 1, 2, 3}, K = 1
Output: 3
Explanation:
Following splits into pair of subsets satisfies the given condition:
- {1, 1, 2}, {3}, difference = (1 + 1 + 2) – 3 = 4 – 3 = 1.
- {1, 3} {1, 2}, difference = (1 + 3) – (1 + 2) = 4 – 3 = 1.
- {1, 3} {1, 2}, difference = (1 + 3) – (1 + 2) = 4 – 3 = 1.
Therefore, the count of ways to split is 3.
Input: arr[] = {1, 2, 3}, K = 2
Output: 1
Explanation:
The only possible split into pair of subsets satisfying the given condition is {1, 3}, {2}, where the difference = (1 + 3) – 2 = 4 – 2 =2.
Therefore, the count of ways to split is 1.
天真的方法:解决给定问题的简单方法是生成所有可能的子集,并将每个子集的总和存储在一个数组中,例如, subset [] 。然后,检查数组subset []中是否存在任何对,其对的差为K。检查所有对之后,将这些对的总数打印为结果。
时间复杂度: O(2 N )
辅助空间: O(2 N )
高效方法:可以通过以下观察对上述方法进行优化。
令第一和第二子集的总和分别为S1和S2 ,并且数组元素的总和为Y。
Now, the sum of both the subsets must be equal to the sum of the array elements.
Therefore, S1 + S2 = Y — (1)
To satisfy the given condition, their difference must be equal to K.
Therefore, S1 – S2 = K — (2)
Adding (1) & (2), the equation obtained is
S1 = (K + Y)/2 — (3)
因此,对于具有和S1和S2的一对子集,等式(3)必须成立,即,子集的元素之和必须等于(K + Y)/ 2 。现在,问题减少到计算具有给定总和的子集的数量。使用动态编程可以解决此问题,其动态关系如下:
dp[i][C] = dp[i + 1][C – arr[i]] + dp[i + 1][C]
在这里, 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.
3
时间复杂度: O(N * K)
辅助空间: O(N * K)