原题链接:https://leetcode-cn.com/problems/target-sum/
相关题目:预测赢家
1、递归
和预测赢家一样,都是有两种选择,并且最后是求和,很容易想到用递归解决
long findTargetSumWays(vector<int>& nums, int S) {
int len=nums.size();
return calculate(nums,len-1,S);
}
long calculate(vector<int>& nums,int i,long S){
if(i==-1){
if(S==0) return 1;
else return 0;
}
return calculate(nums,i-1,S-nums[i])+calculate(nums,i-1,S+nums[i]);
}
2、动态规划
这题的动态规划也不容易想到,需要些技巧
Q表示正和,P表示负和,S表示列表和,T表示目标
Q-P=T
Q+P=S
于是有
2Q=T+S
这样我们就计算和为(T+S)/2的数的组合个数就可以了。于是
dp[i]表示满足和为i的组合个数
状态转移
dp[0]=1;
dp[i]+=dp[i-num];
代码:
int findTargetSumWays(vector<int>& nums, int S) {
long sum=0;
for(int num:nums) sum+=num;
if((S+sum)%2!=0||S>sum) return 0;
int target=(S+sum)/2;
vector<int> dp(target + 1, 0);
dp[0]=1;
for(auto num:nums){
for(int i=target;i>=num;i--){
dp[i]+=dp[i-num];
}
}
return dp[target];
}
不过不能溢出,需要注意一些细节,代码写起来不如递归轻松。但是如果能用一些数学转换,确实能达到事半功倍的效果!