Meet in the middle by subset size
Time O(2ⁿ × n) Space O(2ⁿ)For each half, list subset sums by count. For k = 0..n, sort right[n − k]; for each a in left[k], find b closest to (total − 2a) / 2; the difference is |total − 2(a + b)|.
nums = [3, 9, 7, 3]left [3, 9] by size(map)
right [7, 3] by size(map)
vars(vars)
Step 1/4Team A needs 2 players. The total is 22, so ideally team A has 11.
import java.util.*;
class Solution {
public int minimumDifference(int[] nums) {
int n = nums.length / 2;
long total = 0;
for (int x : nums) total += x;
List<List<Long>> left = bySize(nums, 0, n), right = bySize(nums, n, 2 * n);
long best = Long.MAX_VALUE;
for (int k = 0; k <= n; k++) {
List<Long> r = right.get(n - k);
Collections.sort(r);
for (long a : left.get(k)) {
double want = (total - 2.0 * a) / 2; // ideal b
int lo = 0, hi = r.size();
while (lo < hi) {
int mid = (lo + hi) >>> 1;
if (r.get(mid) < want) lo = mid + 1; else hi = mid;
}
if (lo < r.size()) best = Math.min(best, Math.abs(total - 2 * (a + r.get(lo))));
if (lo > 0) best = Math.min(best, Math.abs(total - 2 * (a + r.get(lo - 1))));
}
}
return (int) best;
}
private List<List<Long>> bySize(int[] nums, int from, int to) {
int m = to - from;
List<List<Long>> out = new ArrayList<>();
for (int i = 0; i <= m; i++) out.add(new ArrayList<>());
for (int mask = 0; mask < (1 << m); mask++) {
long s = 0;
for (int i = 0; i < m; i++) if (((mask >> i) & 1) == 1) s += nums[from + i];
out.get(Integer.bitCount(mask)).add(s);
}
return out;
}
}Verdict: The size grouping keeps the split balanced.