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.
因为这里涉及到多种不同的选择,所以很容易联想到用dfs,代码如下:
 1 class Solution {
 2     public int findTargetSumWays(int[] nums, int S) {
 3         int[] count = { 0 };
 4         helper(nums, 0, S, count);
 5         return count[0];
 6     }
 7     
 8     private void helper(int[] nums, int index, int S, int[] count) {
 9         if (index == nums.length && S == 0) {
10             count[0]++;
11         }
12         if (index >= nums.length) return;
13         helper(nums, index + 1, S + nums[index], count);
14         helper(nums, index + 1, S - nums[index], count);
15     }
16 }

但是这种方法明显是没有优化的,所以时间比其他方法要高。简单的优化就是当我们到了i-th这个位置的时候,如果发现后面部分的值的和或者差都不可能达到target值,我们就应该放弃。

 1 public class Solution {
 2     public int findTargetSumWays(int[] nums, int S) {
 3         if(nums == null || nums.length == 0) return 0;
 4         
 5         int n = nums.length;
 6         int[] sums = new int[n];
 7         int[] count = { 0 };
 8         sums[n - 1] = nums[n - 1];
 9         for (int i = n - 2; i >= 0; i--) {
10             sums[i] = sums[i + 1] + nums[i];
11         }
12         helper(nums, sums, S, 0, count);
13         return count[0];
14     }
15     public void helper(int[] nums, int[] sums, int target, int pos, int[] count){
16         if(pos == nums.length && target == 0){
17             count[0]++;
18         }
19         
20         if (pos == nums.length) return;
21         if (sums[pos] < Math.abs(target)) return;
22         
23         helper(nums, sums, target + nums[pos], pos + 1, count);
24         helper(nums, sums, target - nums[pos], pos + 1, count);
25     }
26 }

还有就是通过dp来做,解法如下:https://leetcode.com/problems/target-sum/discuss/97335/Short-Java-DP-Solution-with-Explanation

this is a classic knapsack problem
in knapsack, we decide whether we choose this element or not
in this question, we decide whether we add this element or minus it

So start with a two dimensional array dp[i][j] which means the number of ways for first i-th element to reach a sum j

 we can easily observe that dp[i][j] = dp[i-1][j+nums[i]] + dp[i-1][j-nums[i],

 Another part which is quite confusing is return value, here we return dp[sum+S], why is that?

because dp's range starts from -sum --> 0 --> +sum
so we need to add sum first, then the total starts from 0, then we add S

Actually most of Sum problems can be treated as knapsack problem, hope it helps

 1 public int findTargetSumWays(int[] nums, int S) {
 2       
 3       int sum = 0;
 4       for(int n: nums){
 5         sum += n;
 6       }
 7       if (S < -sum || S > sum) { return 0;}
 8         
 9       int[][] dp = new int[nums.length + 1][ 2 * sum + 1];
10       dp[0][0 + sum] = 1; // 0 + sum means 0, 0 means -sum,  check below graph
11       for(int i = 1; i <= nums.length; i++){
12         for(int j = 0; j < 2 * sum + 1; j++){
13           
14           if(j + nums[i - 1] < 2  * sum + 1) dp[i][j] += dp[i - 1][j + nums[i - 1]];
15           if(j - nums[i - 1] >= 0) dp[i][j] += dp[i - 1][j - nums[i - 1]];
16         }
17       }
18       return dp[nums.length][sum + S];
19     }

 

转载于:https://www.cnblogs.com/beiyeqingteng/p/11374928.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值