给定一个非负整数数组,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。
注意:
1.数组的长度不会超过20,并且数组中的值全为正数。
2.初始的数组的和不会超过1000。
3.保证返回的最终结果为32位整数。
详见:https://leetcode.com/problems/target-sum/description/
C++:
方法一:
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int res=0;
helper(nums,S,0,res);
return res;
}
void helper(vector<int> &nums,int S,int start,int &res)
{
if(start>=nums.size())
{
if(S==0)
{
++res;
}
return;
}
helper(nums,S-nums[start],start+1,res);
helper(nums,S+nums[start],start+1,res);
}
};
方法二:
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S)
{
int n = nums.size();
vector<unordered_map<int, int>> dp(n + 1);
dp[0][0] = 1;
for (int i = 0; i < n; ++i)
{
for (auto &a : dp[i])
{
int sum = a.first, cnt = a.second;
dp[i + 1][sum + nums[i]] += cnt;
dp[i + 1][sum - nums[i]] += cnt;
}
}
return dp[n][S];
}
};
方法三:
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum=std::accumulate(nums.begin(),nums.end(),0);
return sum<S||(sum+S)&1?0:subSetsum(nums,(sum+S)>>1);
}
int subSetsum(vector<int>& nums, int s){
int dp[s+1]={0};
dp[0]=1;
for(int num:nums)
{
for(int i=s;i>=num;i--)
{
dp[i]+=dp[i-num];
}
}
return dp[s];
}
};
参考:https://www.cnblogs.com/grandyang/p/6395843.html?utm_source=itdadao&utm_medium=referral
https://blog.csdn.net/hit0803107/article/details/54894227
来源:oschina
链接:https://my.oschina.net/u/4332587/blog/3999986