题目:
You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols +
and -
. For each integer, you should choose one from +
and -
as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
Input: nums is [1, 1, 1, 1, 1], S is 3. Output: 5 Explanation: -1+1+1+1+1 = 3 +1-1+1+1+1 = 3 +1+1-1+1+1 = 3 +1+1+1-1+1 = 3 +1+1+1+1-1 = 3 There are 5 ways to assign symbols to make the sum of nums be target 3.
Note:
- The length of the given array is positive and will not exceed 20.
- The sum of elements in the given array will not exceed 1000.
- Your output answer is guaranteed to be fitted in a 32-bit integer.
这题很容易就能用暴力(深度搜索)的解法。但不是最好的解法,可以用动态规划来解,DP 加入“+”和“-”之后原数组的元素可以看成被分成了两个子集合,一个正的子集合P,另一个负的子集合N。使得sum(P)+sum(N) = S,且P+N = nums。不断地简化,最终只要使得sum(P) = (S + sum(nums)) / 2,即可。
具体代码如下:
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum < S || ((S + sum) & 0x1) == 1) {
return 0;
}
int target = (S + sum) >> 1;
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];
}
};
end!