24(May) Partitions with Given Difference
24. Partitions with Given Difference
The problem can be found at the following link: Question Link
Problem Description
Given an array arr
, partition it into two subsets (possibly empty) such that each element must belong to only one subset. Let the sum of the elements of these two subsets be S1
and S2
. Given a difference d
, count the number of partitions in which the difference between S1
and S2
is equal to d
. Since the answer may be large, return it modulo (10^9 + 7).
Example:
Input:
n = 4
d = 3
arr[] = {5, 2, 6, 4}
Output:
1
Explanation: There is only one possible partition of this array. Partition: {6, 4}
, {5, 2}
. The subset difference between subset sums is: (6 + 4) - (5 + 2) = 3
.
Example:
Input:
n = 4
d = 0
arr[] = {1, 1, 1, 1}
Output:
6
Explanation: We can choose two 1
s from indices {0,1}
, {0,2}
, {0,3}
, {1,2}
, {1,3}
, {2,3}
and put them in S1
and the remaining two 1
s in S2
. Thus, there are a total of 6 ways to partition the array arr
.
Approach
Initialization:
Calculate the total sum of the array elements.
If the total sum is less than
d
or if(total_sum - d) % 2
is not zero, return 0, as no valid partition is possible.Define
target = (total_sum - d) / 2
, the sum we need to find in one subset.
Dynamic Programming Table:
Initialize a DP array
dp
of sizetarget + 1
with all zeros.dp[0]
is set to 1 as there is exactly one way to achieve a sum of 0, which is by not picking any elements.
Filling the DP Table:
Iterate through each element in the array.
For each element, update the DP table from
target
down to the element's value to count the number of ways to form each possible sum up totarget
.
Return:
The value
dp[target]
will give the number of ways to partition the array into two subsets with the required difference.
Time and Auxiliary Space Complexity
Expected Time Complexity: O(n * sum(arr)), as we iterate through each element and for each element, we iterate through all possible sums up to
target
.Expected Auxiliary Space Complexity: O(sum(arr)), as we use a DP array of size
target + 1
.
Code
C++
class Solution {
public:
const int MOD = 1000000007;
int findWays(vector<int>& num, int tar) {
int n = num.size();
vector<int> dp(tar + 1, 0);
dp[0] = 1; // Base case: there's one way to make sum 0
for (int ind = 0; ind < n; ind++) {
for (int target = tar; target >= num[ind]; target--) {
dp[target] = (dp[target] + dp[target - num[ind]]) % MOD;
}
}
return dp[tar];
}
int countPartitions(int n, int d, vector<int>& arr) {
int sum = accumulate(arr.begin(), arr.end(), 0);
if (sum < d || (sum - d) % 2 != 0) {
return 0;
}
return findWays(arr, (sum - d) / 2);
}
};
Java
class Solution {
private static final int MOD = 1000000007;
public static int findWays(int[] num, int tar) {
int n = num.length;
int[] dp = new int[tar + 1];
dp[0] = num[0] == 0 ? 2 : 1;
if (num[0] != 0 && num[0] <= tar) {
dp[num[0]] = 1;
}
for (int ind = 1; ind < n; ind++) {
int[] newDp = new int[tar + 1];
for (int target = 0; target <= tar; target++) {
int notTaken = dp[target];
int taken = (target >= num[ind]) ? dp[target - num[ind]] : 0;
newDp[target] = (notTaken + taken) % MOD;
}
dp = newDp;
}
return dp[tar];
}
public int countPartitions(int n, int d, int[] arr) {
int sum = Arrays.stream(arr).sum();
if (sum < d || (sum - d) % 2 != 0) {
return 0;
}
return findWays(arr, (sum - d) / 2);
}
public static void main(String[] args) {
java.util.Scanner sc = new java.util.Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
int n = sc.nextInt();
int d = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
Solution obj = new Solution();
System.out.println(obj.countPartitions(n, d, arr));
}
sc.close();
}
}
Python
from typing import List
class Solution:
MOD = 1000000007
def findWays(self, num: List[int], tar: int) -> int:
dp = [0] * (tar + 1)
dp[0] = 2 if num[0] == 0 else 1
if num[0] != 0 and num[0] <= tar:
dp[num[0]] = 1
for ind in range(1, len(num)):
for target in range(tar, num[ind] - 1, -1):
dp[target] = (dp[target] + dp[target - num[ind]]) % self.MOD
return dp[tar]
def countPartitions(self, n: int, d: int, arr: List[int]) -> int:
total_sum = sum(arr)
if total_sum < d or (total_sum - d) % 2 != 0:
return 0
return self.findWays(arr, (total_sum - d) // 2)
Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: Any Questions. Letβs make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated