假设我们有一个非负整数列表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。因此,有五种分配方法。
为了解决这个问题,我们将遵循以下步骤-
创建一张大小为21 x 2001的表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)从主节调用
让我们看下面的实现以更好地理解-
#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