Subset Sum

Problem Overview
The problem at hand is a well-known challenge related to partitioning and dynamic programming. The task is defined as follows: Given a non-empty array nums
containing positive integers, determine if the array can be partitioned into two subsets whose sums are equal.
Understanding the Problem
To break this problem down, consider an array like [1, 5, 11, 5]
. Our goal is to figure out whether we can divide this array into subsets with equal sum. In this instance, we can form [1, 5, 5]
and [11]
, both of which sum to 11.
The immediate thought might be about finding combinations and checking sums, but with an optimal approach, we aim to utilize dynamic programming (DP) to solve it efficiently.
Key Observation:
- If the total sum of the array is odd, it's immediately impossible to split it into two equal parts.
- If the sum is even, say
2 * target
, then our task reduces to finding a subset of the array that sums totarget
.
Key DSA Concepts and Theory
Dynamic Programming (DP): This is a method for solving complex problems by breaking them down into smaller subproblems, solving each subproblem just once, and storing their solutions. This technique is particularly powerful for optimization problems.
For the partition problem, DP helps in finding if a subset with a particular sum exists. This boils down to a classic DP problem: the "subset sum problem", where we check whether any subset of numbers adds up to a specific target.
DP Array Definition in this Case:
dp[i]
will betrue
if a subset with sumi
can be formed from the elements.
Solution Approach
Step-by-Step Plan
Early Pruning:
- Calculate the total sum. If it is odd, immediately return
false
.
- Calculate the total sum. If it is odd, immediately return
Define the Target:
- If the sum is even, define target as half of total sum:
sum / 2
.
- If the sum is even, define target as half of total sum:
Initialize a DP Array:
- Create a boolean array
dp
of sizetarget + 1
, initialized tofalse
. - Set
dp[0] = true
because a sum of 0 can always be achieved with an empty subset.
- Create a boolean array
Fill the DP Array:
- For each number in the array
nums
:- Traverse backwards from
target
down to the number. - If
dp[j - num]
is true, thendp[j]
should also be true.
- Traverse backwards from
- For each number in the array
Final Decision:
- At the end of processing, if
dp[target]
istrue
, a subset with the desired sum exists, hence returntrue
.
- At the end of processing, if
C++ Code Implementation
#include <vector>
#include <numeric>
class Solution {
public:
bool canPartition(std::vector<int>& nums) {
int sum = std::accumulate(nums.begin(), nums.end(), 0);
// If sum is odd, can't split equally
if (sum % 2 != 0) return false;
int target = sum / 2;
std::vector<bool> dp(target + 1, false);
dp[0] = true; // Base case: 0 sum achievable with empty subset
for (int num : nums) {
for (int j = target; j >= num; --j) {
if (dp[j - num]) {
dp[j] = true;
}
}
}
return dp[target];
}
};
Java Code Implementation
import java.util.Arrays;
class Solution {
public boolean canPartition(int[] nums) {
int sum = Arrays.stream(nums).sum();
// If sum is odd, can't split equally
if (sum % 2 != 0) return false;
int target = sum / 2;
boolean[] dp = new boolean[target + 1];
dp[0] = true; // Base case: 0 sum achievable with empty subset
for (int num : nums) {
for (int j = target; j >= num; --j) {
if (dp[j - num]) {
dp[j] = true;
}
}
}
return dp[target];
}
}
Time and Space Complexity Analysis
Time Complexity: The time complexity is
O(n * target)
wheren
is the number of elements innums
andtarget
is half the sum ofnums
. This is because we iterate through each number and check up to the target sum.Space Complexity: The space complexity is
O(target)
due to thedp
array's size.
Common Mistakes to Avoid
- Not Checking Sum Parity: Make sure to first check if the total sum is odd — an odd total sum means immediate impossibility to partition equally.
- Incorrect DP Array Updates: Avoid updating the
dp
array in a forward manner as it may lead to incorrect results due to overwriting.
Similar Problems on LeetCode
Additional Resources and References
- Dynamic Programming on LeetCode
- Textbooks on algorithm design for deeper understanding of dynamic programming.
- Online resources like Khan Academy or MIT's OpenCourseWare for conceptual overviews of dynamic programming and related problems.