给定一个非负整数数组,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