[Leetcode] DP -- Target Sum

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)

 

转载于:https://www.cnblogs.com/anxin6699/p/7078424.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值