![]() |
VOOZH | about |
Given an array arr[] of length n and an integer target, the task is to find the number of subsets with a sum equal to target.
Examples:
Input: arr[] = [1, 2, 3, 3], target = 6
Output: 3
Explanation: All the possible subsets are [1, 2, 3], [1, 2, 3] and [3, 3]Input: arr[] = [1, 1, 1, 1], target = 1
Output: 4
Explanation: All the possible subsets are [1], [1], [1] and [1]
Table of Content
The problem is to count the number of subsets of a given array arr[] such that the sum of the elements in each subset equals a specified target. A recursive approach is used to solve this problem by considering two cases for each element in the array:
- Exclude the current element: The element at index i is not included in the subset, and the current sum remains unchanged. This leads to the recursion call countSubsets(i + 1, currentSum, target).
- Include the current element: The element at index i is included in the subset, and the sum is updated as currentSum + arr[i]. This leads to the recursion call countSubsets(i + 1, currentSum + arr[i], target).
Please refer to Count of subsets with sum equal to target using Recursion for implementation.
If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming:
1. Optimal Substructure: Maximum subsequence length for a given i, j and currentSum , i.e. countSubsets(i, currentSum, target)ā, depends on the optimal solutions of the subproblems countSubsets(i+1, currentSum, target) and countSubsets(i+1, currentSum + arr[i], target)ā. By choosing the total of these optimal substructures, we can efficiently calculate answer.
2. Overlapping Subproblems: While applying a recursive approach in this problem, we notice that certain subproblems are computed multiple times. For example while considering arr = [1, 1, 2, 3] and target = 10, countSubsets(3, 4, 10, arr) computed multiple times from countSubsets(2, 0, 10, arr) and countSubsets(2, 2, 10, arr).
3
We create a 2D array dp[n+1][target+1], such that dp[i][j] equals to the number of subsets having sum equal to j from subsets of arr[0...i-1].
We fill the dp array as following:
- We initialize all values of dp[i][j] as 0 and we take dp[0][0]=1 because we take empty subset as our base case.
Iterate over all the values of arr[i] from left to right and for each arr[i], iterate over all the possible values of j i.e. from 1 to target (both inclusive) and fill the dp array as following:
dp[i][j] = dp[iĀ-1][j]
if j>=arr[i-1]
dp[i][j] +=dp[iĀ-1][j-arr[i-1]]
This can be explained as there are only two cases either we take element arr[i] or we don't. We take a element only when it's value is less than or equal to j. Then we look for subsets ending at i-1 such that their sum with arr[i] should be equal to j which is given by dp[i-1][j-arr[i-1]]. The number of subsets from set arr[0..n-1] having sum equal to target will be dp[n][target].
3
In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a two 1D array of size target+1 namely prev and curr to store the computations. The final answer is equal to curr[target].
3