494. Target Sum
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.
S1: 2 hash map O(2^n)?
用hash_map记录到目前为止所有的sum和达到sum的可行组合数
int findTargetSumWays(vector<int>& nums, int S) {
unordered_map<int, int> sumCount;
sumCount[0] = 1;
for (int i : nums) {
unordered_map<int, int> nextCount;
for (auto sum : sumCount) {
nextCount[sum.first + i] += sum.second;
nextCount[sum.first - i] += sum.second;
}
sumCount = nextCount;
}
return sumCount[S];
}
S2: DP + math O(mn)
假设最终的sum 由正数部分sum[p]和负数部分sum[n]组成
sum[p] + sum[n] = S => sum[p] + sum[n] + sum[p] - sum[n] = S + sum[p] - sum[n] => 2* sum[p] = S + nums.sum
=> sum[p] = (S + nums.sum) / 2 可转化为求sum为(s + nums.sum)/2的subset的个数。
因为原数组没有负数,S 一定小于nums.sum,S+nums.sum 大于等于0且为偶数
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for (int i : nums) {
sum += i;
}
if (sum + S < 0 || sum < S || (sum + S) & 1) {
return 0;
} else {
return findSum(nums, (sum + S) / 2);
}
}
int findSum(vector<int>& nums, int target) {
vector<int> sumCount(target + 1, 0);
sumCount[0] = 1;
for (int i : nums) {
for (int j = target; j >= i; --j) {
sumCount[j] += sumCount[j - i];
}
}
return sumCount[target];
}
};