Partition Set Into 2 Subsets with Min Absolute Sum Diff
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 20 - ◆
0 ≤ nums[i] ≤ 100
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
BruteEvery number ends up in one of exactly two groups, so assign each one in turn to the first group or leave it for the second, tracking only the running sum of the first group along the way — the second group's sum is always just the total minus that. Once every number has been assigned, the difference between the two group sums can be computed directly, and the smallest difference seen across every possible way of assigning numbers to the first group is the answer. Both choices at every number are explored, since there's no way to know in advance which assignment leads to the smallest final difference.
O(2^n)O(n)1class Solution {
2 private int[] nums;
3 private int total;
4
5 public int minSubsetSumDiff(int[] nums) {
6 this.nums = nums;
7 int total = 0;
8 for (int num : nums) total += num;
9 this.total = total;
10 return solve(0, 0);
11 }
12
13 private int solve(int i, int sum1) {
14 if (i == nums.length) return Math.abs(2 * sum1 - total);
15 return Math.min(solve(i + 1, sum1 + nums[i]), solve(i + 1, sum1));
16 }
17}Optimal — Bottom-Up 1D DP
OptimalWhatever the first group's sum turns out to be, the total minus twice that sum gives the difference between the two groups — so the real question is simply which sums are actually reachable by some subset of the numbers. That's the same reachability sweep used for Subset Sum, run once for every amount up to half the total (going past the halfway point only ever mirrors a smaller, already-checked split). After marking every reachable amount, scanning from 0 up to half the total and keeping the best (smallest) resulting difference among the reachable ones gives the final answer.
O(n × sum)O(sum)1class Solution {
2 public int minSubsetSumDiff(int[] nums) {
3 int total = 0;
4 for (int num : nums) total += num;
5 int half = total / 2;
6 boolean[] dp = new boolean[half + 1];
7 dp[0] = true;
8 for (int num : nums) {
9 for (int s = half; s >= num; s--) {
10 if (dp[s - num]) dp[s] = true;
11 }
12 }
13 int best = Integer.MAX_VALUE;
14 for (int s1 = 0; s1 <= half; s1++) {
15 if (dp[s1]) best = Math.min(best, total - 2 * s1);
16 }
17 return best;
18 }
19}