0%

Leetcode 494 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:

1
2
3
4
5
6
7
8
9
10
11
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.

Constraints:

  • 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.

1 回溯

其实回溯这个名字吧, 说的好听叫回溯, 说的不好听就叫穷举出所有可能.

第一次做这个题只想到了回溯, 没有想到动态规划的方法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
private int ans = 0;
public int findTargetSumWays(int[] nums, int S) {
findTargetSumWays(0, 0, nums, S);
return ans;
}
private void findTargetSumWays(int currSum, int currIndex, int[] nums, int S){
if(currIndex == nums.length){
if(S == currSum){
++ans;
return;
}
else
return;
}
findTargetSumWays(currSum + nums[currIndex], currIndex + 1, nums, S);
findTargetSumWays(currSum - nums[currIndex], currIndex + 1, nums, S);
}
}

2 动态规划

这个动态规划还真不容易想到. 要把答案放在数组里. dp[i][j]表示从nums[0]到nums[i]的子数组中可以组成和为j的方案数. 那么就有dp[i][j] = dp[i - 1][j - nums[i]] + dp[i - 1][j + nums[i]].

同时因为下标不能是负数, 要把第二维的所有下标都加上sum.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
int[][] dp;
public int findTargetSumWays(int[] nums, int S) {
int sum = 0;
for(int i : nums)
sum += i;
final int M = sum;
dp = new int[nums.length][2 * M + 1];
for(int i = 0; i < nums.length; ++i){
if(i == 0){
dp[i][nums[i] + M] += 1;
dp[i][-nums[i] + M] += 1;
}
else{
for(int j = -sum; j <= sum; ++j){
int a1 = (j - nums[i] < -sum) ? 0 : dp[i-1][j - nums[i] + M];
int a2 = (j + nums[i] > sum) ? 0 : dp[i-1][j + nums[i] + M];
dp[i][j + M] += a1 + a2;
}
}
}
return S > M || S < -M ? 0 : dp[nums.length - 1][S + M];
}
}