Problem Description
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.
Answers
class Solution { public: int findTargetSumWays(vector<int>& nums, int s) { int sum = accumulate(nums.begin(), nums.end(), 0); return sum < s || (s + sum) & 1 ? 0 : subsetSum(nums, (s + sum) >> 1); } int subsetSum(vector<int>& nums, int s) { int dp[s + 1] = { 0 }; dp[0] = 1; for (int n : nums) for (int i = s; i >= n; i--) dp[i] += dp[i - n]; return dp[s]; } };
The answer explanation
1. (s + sum) & 1 What is?
& By operating a check (s + sum) may be divisible by 2 if only divisible numbers, can continue operation.
2. (s + sum) >> 1 What is?
Operations divided by 2
3. Why should the above operation?
According to this forum to explain:
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
s + sum needs to be divisible by 2.
4. subsetSum What is the function?
Principle, as shown below (original):