Target Sum
Difficulty: Medium
You're given a list of non-negative integers and a target number. You must place either a + or a - sign in front of every number, then add them all up. Count how many different ways of assigning signs make the total equal the target.
Examples
Input: nums = [1,1,1,1,1], target = 3
Output: 5
The five sign assignments that total 3 are: -1+1+1+1+1, +1-1+1+1+1, +1+1-1+1+1, +1+1+1-1+1, +1+1+1+1-1.
Input: nums = [1], target = 1
Output: 1
Only +1 works.
Constraints
1 <= nums.length <= 20
0 <= nums[i] <= 1000
0 <= sum(nums) <= 1000
-1000 <= target <= 1000
Approach
Assigning signs is the same as splitting the numbers into a "positive group" (sum P) and a "negative group" (sum total - P, where total is the sum of all the numbers). Since the overall result must equal the target, P - (total - P) = target, which rearranges to P = (total + target) / 2.
That turns the problem into ordinary subset counting: how many subsets of nums add up to exactly P? Build a table where cell (i, s) means "using only the first i numbers, how many subsets sum to s?" Each number is either left out of the subset (carry forward the count from one fewer number) or included (add the count for the remaining sum, using one fewer number, since each number is used at most once).
If (total + target) is odd, or the target's absolute value exceeds the total, no split can possibly work, so the answer is immediately 0.
Solutions
Brute Force — Recursion
Try both a plus and a minus sign for every number, recursively, and count how many complete assignments land exactly on the target.
function findTargetSumWays(nums, target) {
function solve(i, total) {
if (i === nums.length) return total === target ? 1 : 0;
return solve(i + 1, total + nums[i]) + solve(i + 1, total - nums[i]);
}
return solve(0, 0);
}Time: O(2^n) · Space: O(n) — recursion depth
Optimal — Subset-Sum Counting with a 2D Table
Reduce sign assignment to counting subsets that sum to a specific target value P, then fill a standard subset-sum-count table indexed by (numbers considered, running sum).
function findTargetSumWays(nums, target) {
const total = nums.reduce((sum, x) => sum + x, 0);
if (Math.abs(target) > total || (total + target) % 2 !== 0) return 0;
const subsetSum = (total + target) / 2;
const n = nums.length;
const table = Array.from({ length: n + 1 }, () => new Array(subsetSum + 1).fill(0));
table[0][0] = 1;
for (let i = 1; i <= n; i++) {
for (let s = 0; s <= subsetSum; s++) {
table[i][s] = table[i - 1][s]; // leave nums[i - 1] out of the subset
if (s - nums[i - 1] >= 0) {
table[i][s] += table[i - 1][s - nums[i - 1]]; // include nums[i - 1] in the subset
}
}
}
return table[n][subsetSum];
}Time: O(n * (total + target)) · Space: O(n * (total + target))