题目:
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.题目解读: 给定一个非负整数数组和一个目标值,你可以给这些数字赋予正负号。问有多少种赋值方式可以使这些数字的和等于目标值
DFS Soulution
class Solution {
public int findTargetSumWays(int[] nums, int S) {
return helper(nums,S,0);
}
public int helper(int[] nums,int target,int start){
if(start == nums.length){
//结束条件
if(target==0) return 1;
else return 0;
}
int count = 0;
count += helper(nums,target-nums[start],start+1);//+号情况
count += helper(nums,target+nums[start],start+1);//-号情况
return count;
}
}
//DP Soulution
/*
Let P be the positive subset and N be the negative subset
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
该问题可以转化为寻找一个子集合P.使得sum(P) = (target+sum(nums))/2
注意target+sum(nums)一定是偶数。这可以作为一个快速判断输入是否有解的依据
*/
class Solution{
public int findTargetSumWays(int[] nums, int S) {
int sum = 0;
for(int i = 0; i < nums.length; i++){
sum += nums[i];
}
return (S > sum || (sum+S) % 2 > 0)? 0 : subSum(nums,(sum+S)/2);
}
public int subSum(int[] nums, int target){
int[] dp = new int[target+1];
dp[0] = 1;
//元素不可重复
for(int num : nums)
for(int j = target; j >= num; j--)
dp[j] += dp[j-num];
return dp[target];
}
}