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.
Note:
- The length of the given array is positive and will not exceed 20.
- The sum of elements in the given array will not exceed 1000.
- Your output answer is guaranteed to be fitted in a 32-bit integer.
LeetCode:链接
先使用数学思路,可以知道赋予标号后,集合中包含负数这正数,则有 sum(Positive)-sum(Negtive) = S。因为sum(Positive)+sum(Negtive)=sum(nums),则有2*sum(Positive)=sum(nums)+S,故sum(Positive)=(sum(nums)+S)/2,由于(sum(nums)+S)/2是固定的整数,所以只需要找到和为它的组合数即可。
举例说明:给定集合nums={1,2,3,4,5}, 求解子集,使子集中元素之和等于9 = new_target = sum(P) = (target+sum(nums))/2
定义dp[10]数组, dp[10] = {1,0,0,0,0,0,0,0,0,0}
dp[i]表示子集合元素之和等于当前目标值的方案个数, 当前目标值等于9减去当前元素值
当前元素等于1时,dp[9] = dp[9] + dp[9-1]
dp[8] = dp[8] + dp[8-1]
...
dp[1] = dp[1] + dp[1-1]
当前元素等于2时,dp[9] = dp[9] + dp[9-2]
dp[8] = dp[8] + dp[8-2]
...
dp[2] = dp[2] + dp[2-2]
当前元素等于3时,dp[9] = dp[9] + dp[9-3]
dp[8] = dp[8] + dp[8-3]
...
dp[3] = dp[3] + dp[3-3]
当前元素等于4时,
...
当前元素等于5时,
...
dp[5] = dp[5] + dp[5-5]
最后返回dp[9]即是所求的解。
class Solution(object):
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
if sum(nums) < S:
return 0
'''如果不能被整除 说明没有这么多正数'''
if (sum(nums) + S) % 2 == 1:
return 0
target = (sum(nums) + S) / 2
dp = [0] * (target+1)
dp[0] = 1
for n in nums:
i = target
while i >= n:
dp[i] = dp[i] + dp[i-n]
i -= 1
return dp[target]