给定一个非负整数数组,a1, a2, …, an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 +
或 -
中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
示例 1:
输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释:
-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
一共有5种方法让最终目标和为3。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int count = 0;
bt(0,0,nums,S,count);
return count;
}
void bt(int i, int cursum, vector<int>& nums, int &S, int &count)
{
if(i == nums.size())
{
if(cursum == S)
++count;
return;
}
bt(i+1,cursum+nums[i],nums,S,count);
bt(i+1,cursum-nums[i],nums,S,count);
}
};
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int count = 0, n, lv = 0;
queue<int> q;
q.push(0);
while(!q.empty())
{
n = q.size();
while(n--)
{
if(lv == nums.size())
{
if(q.front()==S)
++count;
q.pop();
}
else
{
q.push(q.front()+nums[lv]);
q.push(q.front()-nums[lv]);
q.pop();
}
}
lv++;
}
return count;
}
};
参考别人的
假设P是正子集,N是负子集 例如: 假设nums = [1, 2, 3, 4, 5],target = 3,一个可能的解决方案是+1-2+3-4+5 = 3 这里正子集P = [1, 3, 5]和负子集N = [2, 4]
如何将其转换为子集求和问题:
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
原来的问题转化为一个求子集的和问题: 找到nums的一个子集 P,使得sum( P ) = (target + sum(nums)) / 2,从上面最后个式子,可看出 target+sum(nums) 为偶数
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int i, j, sum_nums = 0;
for(i = 0; i < nums.size(); ++i)
sum_nums += nums[i];
if((long(sum_nums)+S)%2 != 0 || S > sum_nums)
return 0;
S = (S+sum_nums)>>1;
long *dp = new long [S+1];
memset(dp,0,(S+1)*sizeof(long));
dp[0] = 1;
for(i = 0; i < nums.size(); ++i)
{
for(j = S; j >= 0; --j)
{
if(dp[j] != 0 && j+nums[i] <= S)
dp[j+nums[i]] += dp[j];
}
}
return dp[S];
}
};