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.
//设输入非负整数总和为sum, 根据题意, 正数集合之和P与负数集合之和N之差就是所求的目标值S, 即 S = P - N;
//又因为 P + N = sum, 故由 P + N + S = P - N + P + N, 即有P = (P + N + S)/2 = (sum + S) / 2;
//因此, 只要统计原整数集合nums的能够求和得到大小为P的子集个数, 将其返回, 就得到当前问题解的个数.
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int pNums = 0;//'+'整数集之和
int sum = 0;//nums之和
int count = 0;
for(auto itr : nums){
sum += itr;
}
if (S > sum || (sum + S) % 2) return 0;//检查是否合法
pNums = (S + sum) / 2;
int dp[pNums + 1] ={0};//动态规划,统计nums中,所有整数之和为1 ~ pNums 的子集个数
dp[0] = 1;
for(auto i : nums){
for(int j = pNums; j>=i; --j){
dp[j] += dp[j - i];
}//for
}//for
return dp[pNums];//返回nums中整数之和大小为pNums的子集个数
}
};