给定一个由N 个整数和一个整数K组成的数组arr[] ,任务是找到将数组拆分为一对子集的方法数,使得它们的总和之间的差为K 。
例子:
Input: arr[] = {1, 1, 2, 3}, K = 1
Output: 3
Explanation:
Following splits into a 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 a 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[] 。然后,检查数组子集 [] 中是否存在差为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.
Javascript
3
时间复杂度: O(N*K)
辅助空间: O(N*K)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。