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.
class Solution { public: int res; void dfs(vector<int>& nums, int idx, int sum, int t){ if(sum == t) res++; else if(sum < t){ for(int i = idx + 1; i < nums.size(); i++) dfs(nums, i, sum + nums[i], t); } else if(sum > t) return ; } int findTargetSumWays(vector<int>& nums, int S) { int sum = 0, cnt0 = 0; for(int i = 0; i < nums.size(); i++){ sum += nums[i]; if(nums[i] == 0) cnt0++; } nums.erase(remove(nums.begin(), nums.end(), 0), nums.end()); int t = sum - S; if(t & 1 || t < 0) return 0; dfs(nums, -1, 0, t >> 1); return res * pow(2, cnt0); } };
class Solution { public: int findTargetSumWays(std::vector<int>& nums, int S) { int sum = std::accumulate(nums.begin(), nums.end(), 0); return sum < S || (sum - S) & 1 ? 0 : subsetSum(nums, (sum-S) >> 1); } int subsetSum(std::vector<int>& nums, int s) { int dp[s+1]; memset(dp, 0, sizeof(int)*(s+1)); dp[0] = 1; for(int n: nums) { for (int i = s; i >= n; --i) { dp[i] += dp[i-n]; } } return dp[s]; } };