You are given an integer array nums and an integer target.

You want to build an expression out of nums by adding one of the symbols + and - before each integer in nums and then concatenate all the integers.

For example, if nums = [2, 1], you can add a + before 2 and a - before 1 and concatenate them to build the expression "+2-1".

Return the number of different expressions that you can build, which evaluates to target.

Examples

Example 1:

Input: nums = [1,1,1,1,1], target = 3
Output: 5
Explanation: There are 5 ways to assign symbols to make the sum of nums equal to target 3.
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

Example 2:

Input: nums = [1], target = 1
Output: 1

Constraints

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • -1000 <= target <= 1000

Thinking Process

  1. Mathematical Transformation: Convert to subset sum problem
  • Define state: what subproblem does dp[i] (or dp[i][j]) represent?
  • Recurrence: how does the answer build from smaller indices?
  • Base cases first; optimize space if only prior row/layer is needed.
1D DP recurrence dp[i] 0 1 2 ? dp[i] from smaller indices / subproblems

Common Approaches

Typical techniques for this pattern:

Approach Time Space Notes
1D DP (this problem) O(n) O(n) or O(1) Linear recurrence
2D DP O(nm) O(nm) or O(n) Grid or two-sequence problems
State machine DP O(n) O(1) Buy/sell, hold/not-hold states
Memoization (top-down) Same as DP O(n) Recursive + cache

Solution

Time Complexity: O(n × sum)
Space Complexity: O(sum)

Convert the problem to a subset sum problem using mathematical transformation.

class Solution:
    def findTargetSumWays(self, nums: list[int], target: int) -> int:
        totalSum = sum(nums)

        # invalid cases
        if abs(target) > totalSum or (target + totalSum) % 2 != 0:
            return 0

        subsetSum = (target + totalSum) // 2

        dp = [0] * (subsetSum + 1)
        dp[0] = 1

        for num in nums:
            for i in range(subsetSum, num - 1, -1):
                dp[i] += dp[i - num]

        return dp[subsetSum]

Solution Explanation

Approach: 1D DP (this problem)

Key idea: 1. Mathematical Transformation: Convert to subset sum problem

How the code works:

  1. Mathematical Transformation: Convert to subset sum problem
    • Define state: what subproblem does dp[i] (or dp[i][j]) represent?
    • Recurrence: how does the answer build from smaller indices?
    • Base cases first; optimize space if only prior row/layer is needed.

Walkthrough — input nums = [1,1,1,1,1], target = 3, expected output 5:

There are 5 ways to assign symbols to make the sum of nums equal to target 3. -1 + 1 + 1 + 1 + 1 = 3 +1 - 1 + 1 + 1 + 1 = 3 +1 + 1 - 1 + 1 + 1 = 3 +1 + 1 + 1 - 1 + 1 = 3 +1 + 1 + 1 + 1 - 1 = 3

| Approach | Time Complexity | Space Complexity | |———-|—————-|——————| | Brute Force | O(2^n) | O(n) | | Memoization | O(n × sum) | O(n × sum) | | DP (Subset Sum) | O(n × sum) | O(sum) |

Algorithm Breakdown

1. Validation Check

if (target + totalSum) % 2 != 0  or  abs(target) > totalSum:
    return 0




Why this check?

  • If (target + totalSum) is odd, subsetSum would be fractional (impossible)
  • If abs(target) > totalSum, it’s impossible to achieve the target

2. Subset Sum Calculation

subsetSum = (target + totalSum) / 2

Mathematical proof:

  • S+ - S- = target (equation 1)
  • S+ + S- = totalSum (equation 2)
  • Adding equations: 2S+ = target + totalSum
  • Therefore: S+ = (target + totalSum) / 2

3. DP Array Initialization

list[int] dp(subsetSum + 1, 0)
dp[0] = 1  # One way to make sum 0 (empty subset)

4. Bottom-Up DP

for num in nums:
    for i in range(subsetSum, num - 1, -1):
        dp[i] += dp[i - num]

Why iterate backwards?

  • Prevents using the same number twice in one iteration
  • Ensures we only use numbers from previous iterations

Complexity

| Approach | Time Complexity | Space Complexity | |———-|—————-|——————| | Brute Force | O(2^n) | O(n) | | Memoization | O(n × sum) | O(n × sum) | | DP (Subset Sum) | O(n × sum) | O(sum) |

Common Mistakes

  1. Impossible target: nums = [1], target = 20
  2. Single element: nums = [1], target = 11
  3. Zero target: nums = [1,1], target = 02
  4. Large numbers: nums = [1000], target = 10001

  5. Forgetting validation: Not checking if target is achievable
  6. Wrong iteration order: Using forward iteration in DP
  7. Incorrect subset sum formula: Wrong calculation of subsetSum
  8. Array bounds: Not handling edge cases properly

Why This Solution is Optimal

  1. Mathematical Insight: Transforms exponential problem to polynomial
  2. Space Efficient: Uses 1D DP array instead of 2D
  3. Early Termination: Validates feasibility before computation
  4. Optimal Complexity: O(n × sum) is the best possible for this problem

References

Key Takeaways

  1. Mathematical Transformation: Convert to subset sum problem
  2. DP Optimization: Use 1D array instead of 2D
  3. Backward Iteration: Prevents double counting
  4. Early Validation: Check feasibility before computation