C ++中的目标总和
假设我们有一个非负整数列表a1,a2,...,an和另一个值,即目标S。现在我们有2个符号+和-。对于每个整数,我们应从+和-中选择一个作为其新符号。我们必须找出几种分配符号的方法,以使整数和与目标值S相同。因此,如果数字为[1,1,1,1,1,1]且S=3,则输出将为5,因为组合是–1+1+1+1+1=3,+1-1+1+1+1=1=3,+1+1-1–1+1+1=3,+1+1+1–1+1=3,+1+1+1+1–1=3。因此,有五种分配方法。
为了解决这个问题,我们将遵循以下步骤-
创建一张大小为21x2001的表dp,并用–1填充。这将用于动态编程方法
递归方法将称为solve()。这将采用pos,数组v,tempSum和实际总和S。这将如下所示:
如果pos与数组v的大小相同,则如果s=tempSum,则返回true,否则返回false
如果dp[pos,tempSum+1000]不为-1,则返回dp[pos,tempSum+1000]
ans:=solve(pos+1,v,tempSum–v[pos],s)+solve(pos+1,v,tempSum+v[pos],s)
dp[pos,tempSum+1000]=ans
返回ans
solve()使用参数solve(0,nums,0,s)从主节调用
例子(C++)
让我们看下面的实现以更好地理解-
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int dp[21][2001];
int solve(int pos, vector <int> v, int tempSum, int s){
if(pos == v.size()){
return s == tempSum;
}
if(dp[pos][tempSum+1000]!=-1)return dp[pos][tempSum+1000];
int ans = solve(pos+1,v,tempSum-v[pos],s) +solve(pos+1,v,tempSum+v[pos],s);
dp[pos][tempSum+1000] = ans;
return ans;
}
int findTargetSumWays(vector<int>& nums, int s) {
int n = nums.size();
if(s>1000)return 0;
for(int i =0;i<21;i++){
for(int j =0;j<2001;j++){
dp[i][j] = -1;
}
}
return solve(0,nums,0,s);
}
};
main(){
Solution ob;
vector<int> v = {1,1,1,1,1};
cout << ob.findTargetSumWays(v, 3);
}输入值
[1,1,1,1,1] 3
输出结果
5