Subset Sum
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 20 - ◆
0 ≤ nums[i] ≤ 100 - ◆
0 ≤ target ≤ 1000
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Recursive Without Memoization
BruteAt every number, there are exactly two choices: leave it out of the subset, or include it and subtract its value from the amount still needed. Either choice is worth exploring, since only one of them might eventually lead to a remaining amount of exactly zero — the signal that a valid subset has been found. Running out of numbers before reaching zero, or going negative by including a number that's too large, both mean that particular path fails. Trying every combination of include/exclude decisions answers the question, though the same (index, remaining) situation can be revisited many times along different paths.
O(2^n)O(n)1class Solution {
2 private int[] nums;
3
4 public boolean subsetSum(int[] nums, int target) {
5 this.nums = nums;
6 return solve(0, target);
7 }
8
9 private boolean solve(int i, int remaining) {
10 if (remaining == 0) return true;
11 if (i == nums.length || remaining < 0) return false;
12 return solve(i + 1, remaining) || solve(i + 1, remaining - nums[i]);
13 }
14}Optimal — Bottom-Up 1D DP
OptimalTrack, for every amount from 0 up to target, whether some subset of the numbers seen so far can reach it exactly — a single boolean array indexed by amount. Amount 0 is always reachable (the empty subset), and each number, in turn, can extend any amount that was already reachable before it by that number's value. Sweeping each number's inner update from target down to the number's own value guarantees that number is only ever counted once per amount (using the array's state from before this number was considered), which is exactly what "subset" — as opposed to reusing a number — requires. After every number has been swept through, the entry at target holds the final answer.
O(n × target)O(target)1class Solution {
2 public boolean subsetSum(int[] nums, int target) {
3 boolean[] dp = new boolean[target + 1];
4 dp[0] = true;
5 for (int num : nums) {
6 for (int s = target; s >= num; s--) {
7 if (dp[s - num]) dp[s] = true;
8 }
9 }
10 return dp[target];
11 }
12}