PracticeNeetCode ↗LeetCode ↗
Given an array of non-negative integers nums and an integer target, assign a + or - sign to each number so the whole expression evaluates to target. Return how many different sign assignments achieve that.
-sum(nums) and sum(nums), so a dictionary keyed by (index, total) is a compact, effective cache.target.dfs(i, total): the number of ways to reach target using nums[i:], given the running total so far.i == len(nums), return 1 if total == target, else 0.dfs(i+1, total + nums[i]) and dfs(i+1, total - nums[i]) — and sum them.(i, total) result the first time it's computed, and reuse it on repeat visits.dfs(0, 0).Time: O(n · range of possible sums) — Space: O(n · range of possible sums)
def findTargetSumWays(nums: list[int], target: int) -> int:
memo = {}
def dfs(i: int, total: int) -> int:
if i == len(nums):
return 1 if total == target else 0
if (i, total) in memo:
return memo[(i, total)]
memo[(i, total)] = dfs(i + 1, total + nums[i]) + dfs(i + 1, total - nums[i])
return memo[(i, total)]
return dfs(0, 0)How the solution above works, piece by piece.
dfs(i, total) = number of ways to assign signs to nums[i:] so the final total equals target, given the running total so far.i == len(nums)) there is 1 way if the total matches, else 0.dfs(i + 1, total + nums[i]) + dfs(i + 1, total - nums[i]).(i, total); memo stores each result so it's computed once.Running it on nums = [1, 1, 1, 1, 1], target = 3:
(i, total), so no state is recomputed.