给定一个大小为N的数组A[]和一个整数diff ,任务是计算将数组分成两个子集(非空子集是可能的)的方法数量,使得它们的总和之间的差等于diff 。
例子:
Input: A[] = {1, 1, 2, 3}, diff = 1
Output: 3
Explanation: All possible combinations are as follows:
- {1, 1, 2} and {3}
- {1, 3} and {1, 2}
- {1, 2} and {1, 3}
All partitions have difference between their sums equal to 1. Therefore, the count of ways is 3.
Input: A[] = {1, 6, 11, 5}, diff=1
Output: 2
朴素方法:解决问题的最简单方法是基于以下观察:
Let the sum of elements in the partition subsets S1 and S2 be sum1 and sum2 respectively.
Let sum of the array A[] be X.
Given, sum1 – sum2 = diff – (1)
Also, sum1 + sum2 = X – (2)
From equations (1) and (2),
sum1 = (X + diff)/2
因此,任务被简化为找到具有给定总和的子集数量。
因此,解决这个问题最简单的方法是生成所有可能的子集并检查该子集是否具有所需的总和。
时间复杂度: O(2 N )
辅助空间: O(N)
高效的方法:为了优化上述方法,思想是使用动态规划。初始化一个大小为N*X的dp[][]表,其中dp[i][C]存储子数组A[i…N-1]的子集数量,使得它们的总和等于C 。因此,递归是非常微不足道的,因为只有两种选择,即要么考虑子集中的第i个元素,要么不考虑。所以递归关系将是:
dp[i][C] = dp[i – 1][C – A[i]] + dp[i-1][C]
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to count the number of ways to divide
// the array into two subsets and such that the
// difference between their sums is equal to diff
int countSubset(int arr[], int n, int diff)
{
// Store the sum of the set S1
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
sum += diff;
sum = sum / 2;
// Initializing the matrix
int t[n + 1][sum + 1];
// Number of ways to get sum
// using 0 elements is 0
for (int j = 0; j <= sum; j++)
t[0][j] = 0;
// Number of ways to get sum 0
// using i elements is 1
for (int i = 0; i <= n; i++)
t[i][0] = 1;
// Traverse the 2D array
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
// If the value is greater
// than the sum store the
// value of previous state
if (arr[i - 1] > j)
t[i][j] = t[i - 1][j];
else {
t[i][j] = t[i - 1][j]
+ t[i - 1][j - arr[i - 1]];
}
}
}
// Return the result
return t[n][sum];
}
// Driver Code
int main()
{
// Given Input
int diff = 1, n = 4;
int arr[] = { 1, 1, 2, 3 };
// Function Call
cout << countSubset(arr, n, diff);
}
Java
// Java program for the above approach
import java.io.*;
public class GFG
{
// Function to count the number of ways to divide
// the array into two subsets and such that the
// difference between their sums is equal to diff
static int countSubset(int []arr, int n, int diff)
{
// Store the sum of the set S1
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
sum += diff;
sum = sum / 2;
// Initializing the matrix
int t[][] = new int[n + 1][sum + 1];
// Number of ways to get sum
// using 0 elements is 0
for (int j = 0; j <= sum; j++)
t[0][j] = 0;
// Number of ways to get sum 0
// using i elements is 1
for (int i = 0; i <= n; i++)
t[i][0] = 1;
// Traverse the 2D array
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
// If the value is greater
// than the sum store the
// value of previous state
if (arr[i - 1] > j)
t[i][j] = t[i - 1][j];
else {
t[i][j] = t[i - 1][j]
+ t[i - 1][j - arr[i - 1]];
}
}
}
// Return the result
return t[n][sum];
}
// Driver Code
public static void main(String[] args)
{
// Given Input
int diff = 1, n = 4;
int arr[] = { 1, 1, 2, 3 };
// Function Call
System.out.print(countSubset(arr, n, diff));
}
}
// This code is contributed by AnkThon
Python3
# Python3 program for the above approach
# Function to count the number of ways to divide
# the array into two subsets and such that the
# difference between their sums is equal to diff
def countSubset(arr, n, diff):
# Store the sum of the set S1
sum = 0
for i in range(n):
sum += arr[i]
sum += diff
sum = sum // 2
# Initializing the matrix
t = [[0 for i in range(sum + 1)]
for i in range(n + 1)]
# Number of ways to get sum
# using 0 elements is 0
for j in range(sum + 1):
t[0][j] = 0
# Number of ways to get sum 0
# using i elements is 1
for i in range(n + 1):
t[i][0] = 1
# Traverse the 2D array
for i in range(1, n + 1):
for j in range(1, sum + 1):
# If the value is greater
# than the sum store the
# value of previous state
if (arr[i - 1] > j):
t[i][j] = t[i - 1][j]
else:
t[i][j] = t[i - 1][j] + t[i - 1][j - arr[i - 1]]
# Return the result
return t[n][sum]
# Driver Code
if __name__ == '__main__':
# Given Input
diff, n = 1, 4
arr = [ 1, 1, 2, 3 ]
# Function Call
print (countSubset(arr, n, diff))
# This code is contributed by mohit kumar 29
C#
// C# program for the above approach
using System;
public class GFG
{
// Function to count the number of ways to divide
// the array into two subsets and such that the
// difference between their sums is equal to diff
static int countSubset(int []arr, int n, int diff)
{
// Store the sum of the set S1
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
sum += diff;
sum = sum / 2;
// Initializing the matrix
int [,]t = new int[n + 1, sum + 1];
// Number of ways to get sum
// using 0 elements is 0
for (int j = 0; j <= sum; j++)
t[0,j] = 0;
// Number of ways to get sum 0
// using i elements is 1
for (int i = 0; i <= n; i++)
t[i,0] = 1;
// Traverse the 2D array
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
// If the value is greater
// than the sum store the
// value of previous state
if (arr[i - 1] > j)
t[i,j] = t[i - 1,j];
else {
t[i,j] = t[i - 1,j]
+ t[i - 1,j - arr[i - 1]];
}
}
}
// Return the result
return t[n,sum];
}
// Driver Code
public static void Main(string[] args)
{
// Given Input
int diff = 1, n = 4;
int []arr = { 1, 1, 2, 3 };
// Function Call
Console.Write(countSubset(arr, n, diff));
}
}
// This code is contributed by AnkThon
Javascript
3
时间复杂度: O(S*N),其中 S =数组元素总和+ K/2
辅助空间: O(S*N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。