假设我们有一个非负整数列表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