You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols +
and -
. For each integer, you should choose one from +
and -
as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
Input: nums is [1, 1, 1, 1, 1], S is 3. Output: 5 Explanation: -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 There are 5 ways to assign symbols to make the sum of nums be target 3.
Solution:
1st use DFS recursive, like a binary tree; Go to left (+1) or right (-1); then when sum is S go the upper next。
But it is
TLE in python
1 count = 0 2 def findTargetSumWays(self, nums, S): 3 def findTargetHelper(nums, index, S): 4 if index == len(nums): 5 if S == 0: 6 self.count = self.count + 1 7 return 8 9 10 findTargetHelper(nums, index+1, S - nums[index]) #+1 11 findTargetHelper(nums, index+1, S + nums[index]) #-1 12 13 findTargetHelper(nums, 0, S) 14 15 return self.count
2.
DP
Refer to the other's idea that I didn't came up with .
this problem could be transferred to subset sum problem (similar to knapback problem)
if there exist a solution,
P: positive number subset; N: positive number subset
then sum(P) - sum(N) = S
; |P| + |N| = len(nums)
so sum(P) + sum(N) + sum(P) - sum(N) = S + sum(P) + sum(N)
2*sum(P) = S + sum(nums)
sum(P) = (S + sum(nums))/2
the original problem has been changed to a subset sum problem: :
Find a subset
P
of
nums
such that
sum(P) = (target + sum(nums)) / 2
1 def subsetSum(nums, target): 2 dp = [0]*(target+1) 3 dp[0] = 1 4 for num in nums: 5 for j in range(target, num-1, -1): 6 dp[j] += dp[j-num] 7 #print ("dp: ", target, j, dp[j]) 8 return dp[target] 9 10 sumN = sum(nums) 11 12 if sumN < S or (S+sumN) %2 != 0: 13 return 0 14 return subsetSum(nums, (S+sumN)>>1)