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 be- trueif a subset with sum- ican 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 dpof sizetarget + 1, initialized tofalse.
- Set dp[0] = truebecause 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 targetdown 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)where- nis the number of elements in- numsand- targetis half the sum of- nums. 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 the- dparray'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 dparray 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.