目标和
题面
leetcode题目
给你一个整数数组 和一个整数 。
向数组中的每个整数前添加 或 ,然后串联起所有整数,可以构造一个 表达式 :
- 例如, ,可以在 之前添加 ,在 之前添加 ,然后串联起来得到表达式 。
返回可以通过上述方法构造的、运算结果等于 的不同 表达式 的数目。
example
输入:,
输出:
解释:一共有 种方法让最终目标和为 。
数据范围
题解
总体思路
还是考虑01背包,因为只有两种状态,当前值前添加和添加。
考虑表示在维护结束第个元素后目标和为时的表达式的数量,那么有:
于是有: 考虑到我们c++中维护负数下标的复杂性,我们不妨直接把数字0定义成一个比较大的值,然后向左右扩展。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include <iostream> #include <vector> #include <string> #include <map> #include <cstring> using namespace std;
#define _DEBUG class Solution { public: const int MAX = 2011; const int ZERO = 1010; int findTargetSumWays(vector<int> &nums, int target) { int len = nums.size(); int dp[len + 1][MAX]; memset(dp, 0, sizeof(dp)); dp[0][ZERO] = 1;
for (int i = 1; i <= len; i++) { int num = nums[i - 1]; for (int k = 1; k < MAX; k++) { if (k - num >= 0) { dp[i][k] += dp[i - 1][k - num]; } if (k + num < MAX) { dp[i][k] += dp[i - 1][k + num]; } #ifdef _DEBUG if (dp[i][k] > 0) { cout << "i: " << i << " k: " << k << " dp: " << dp[i][k] << endl; } #endif } } return dp[len][ZERO + target]; } };
int main() { Solution s; vector<int> t1{1, 1, 1, 1, 1}; cout << s.findTargetSumWays(t1, 3) << endl; vector<int> t2{1}; cout << s.findTargetSumWays(t2, 1) << endl; return 0; }
|