| Difficulty | Medium | |
|---|---|---|
| Source | 160 Days of Problem Solving | |
| Tags |
|
The problem can be found at the following link: Question Link
Given an array of positive integers arr[] and a target value sum, determine if there exists a subset of arr[] whose sum is exactly equal to the given sum.
arr[] = {3, 34, 4, 12, 5, 2}
sum = 9trueA subset {4, 3, 2} exists with sum = 9.
arr[] = {3, 34, 4, 12, 5, 2}
sum = 30falseThere is no subset with sum = 30.
arr[] = {1, 2, 3}
sum = 6trueThe entire array {1, 2, 3} forms the subset with sum = 6.
$1 \leq \text{size of arr} \leq 200$ $1 \leq arr[i] \leq 200$ $1 \leq sum \leq 10^4$
-
Define a boolean DP array
dp[sum + 1], wheredp[j]tells whether sumjis possible. -
Base Case:
dp[0] = true(sum 0 is always achievable). -
Iterate through each number in the array and update
dp[j]for alljfromsumdown tonum. -
Transition Formula:
$[ \text{dp}[j] = \text{dp}[j] \ OR\ \text{dp}[j - \text{num}] $ ]- If
dp[j - num]wastrue, thendp[j]can also becometrueby includingnum.
- If
-
Return
dp[sum]as the final answer.
- Expected Time Complexity: O(N × sum), since we iterate through all elements and update the DP table.
- Expected Auxiliary Space Complexity: O(sum), as we use a 1D array of size
sum + 1.
class Solution {
public:
bool isSubsetSum(vector<int>& arr, int sum) {
vector<bool> dp(sum + 1, false);
dp[0] = true;
for (int num : arr)
for (int j = sum; j >= num; --j)
dp[j] = dp[j] || dp[j - num];
return dp[sum];
}
};⚡ Alternative Approaches
2️⃣ Dynamic Programming (O(N×sum) Time, O(N×sum) Space) — 2D DP
Algorithm Steps:
- Use a 2D DP table where
dp[i][j]represents whether it's possible to achieve sumjusing the firstielements. -
Base Case:
-
dp[i][0] = truefor alli(sum0is always achievable). -
dp[0][j] = falseforj > 0(no elements can't form non-zero sum).
-
-
Recurrence Relation:
$[ \text{dp}[i][j] = \text{dp}[i-1][j] || \text{dp}[i-1][j - arr[i-1]] $ ]- Exclude the element (
dp[i-1][j]). - Include the element (
dp[i-1][j - arr[i-1]]).
- Exclude the element (
class Solution {
public:
bool isSubsetSum(vector<int>& arr, int sum) {
int n = arr.size();
vector<vector<bool>> dp(n + 1, vector<bool>(sum + 1, false));
for (int i = 0; i <= n; i++) dp[i][0] = true;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
dp[i][j] = dp[i - 1][j];
if (j >= arr[i - 1]) dp[i][j] |= dp[i - 1][j - arr[i - 1]];
}
}
return dp[n][sum];
}
};✅ Time Complexity: O(N × sum)
✅ Space Complexity: O(N × sum)
3️⃣ Recursive + Memoization (O(N×sum) Time, O(N×sum) Space)
Algorithm Steps:
- Define a recursive function
solve(index, sum):- Base Case: If
sum == 0, returntrue. - If
index < 0orsum < 0, returnfalse. - Memoize results to avoid recomputation.
- Base Case: If
-
Recurrence Relation:
$[ \text{solve(index, sum)} = \text{solve(index - 1, sum)} \quad \text{OR} \quad \text{solve(index - 1, sum - arr[index])} ]$ - Exclude the element.
- Include the element.
-
Use memoization (
dp[index][sum]) to avoid redundant calculations.
class Solution {
public:
vector<vector<int>> dp;
bool solve(vector<int>& arr, int i, int sum) {
if (sum == 0) return true;
if (i < 0 || sum < 0) return false;
if (dp[i][sum] != -1) return dp[i][sum];
return dp[i][sum] = solve(arr, i - 1, sum) || solve(arr, i - 1, sum - arr[i]);
}
bool isSubsetSum(vector<int>& arr, int sum) {
int n = arr.size();
dp.assign(n, vector<int>(sum + 1, -1));
return solve(arr, n - 1, sum);
}
};✅ Time Complexity: O(N × sum)
✅ Space Complexity: O(N × sum)
Comparison of Approaches
| Approach | ⏱️ Time Complexity | 🗂️ Space Complexity | ✅ Pros | |
|---|---|---|---|---|
| 1D Space Optimized DP | 🟡 O(N × sum)
|
🟢 O(sum)
|
Most efficient space-wise | Requires careful indexing |
| 2D DP (Tabulation) | 🟡 O(N × sum)
|
🔴 O(N × sum)
|
Easy to implement, intuitive | High space usage |
| Recursive + Memoization | 🟡 O(N × sum)
|
🔴 O(N × sum)
|
Natural recursion flow | Stack overhead |
✅ Best Choice?
- If optimizing space: Use 1D DP (Space-Optimized).
- If space is not a concern: Use 2D DP (Tabulation) for easy understanding.
- For recursion lovers: Use Recursive + Memoization.
class Solution {
static boolean isSubsetSum(int[] arr, int sum) {
boolean[] dp = new boolean[sum + 1];
dp[0] = true;
for (int num : arr)
for (int j = sum; j >= num; --j)
dp[j] |= dp[j - num];
return dp[sum];
}
}class Solution:
def isSubsetSum(self, arr, sum):
dp = [False] * (sum + 1)
dp[0] = True
for num in arr:
for j in range(sum, num - 1, -1):
dp[j] |= dp[j - num]
return dp[sum]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! ⭐