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.
简单的可以用递归方法来做,令f(i, s)表示前i个整数目标和为s的方式,则f(i, s)=f(i-1, s+nums[i]) + f(i-1,s-nums[i]). 当i=0时,f(0, s)=0;当i=1, nums[0]=0时,f(1,0)=2;当i=1,s=nums[0]!=0时,f(1,s)=1,否则f(1,s)=0.
也可以用动态规划来做,令A为符号为+的集合,B为符号为-的集合,则
sum(A)-sum(B)=S;
sum(A)-sum(B)+sum(A)+sum(B)=S+sum(A)+sum(B)=S+sum(nums);
2sum(A)=S+sum(nums);
sum(A)=1/2*(S+sum(nums));
现在问题转化为nums[]中有多少种集合A的方式使得A中所有数的和为1/2*(S+sum(nums)).
递归的代码为:
class Solution {
public:
int findTargetSumWays(vector<int> nums, int S) {
int size=nums.size();
int temp;
vector<int>::iterator it=nums.begin();
if(size==0)
{
return 0;
}
else if(size==1)
{
if(*it==S&&*it==(-S))
return 2;
else if(*it==S||*it==(-S))
return 1;
else
return 0;
}
else
{
temp=nums[size-1];
nums.erase(it+size-1);
return findTargetSumWays(nums,S-temp)+findTargetSumWays(nums,S+temp);
}
}
};