494. Target Sum
阿新 • • 發佈:2020-07-16
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.
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.
class Solution { int res = 0; public int findTargetSumWays(int[] nums, int S) {if(nums.length == 0) return 0; dfs(nums, S, 0, 0); return res; } public void dfs(int[] nums, int S, int pos, int cur){ if(pos == nums.length) { if(cur == S) res++; return; } dfs(nums, S, pos + 1, cur + nums[pos]); dfs(nums, S, pos+ 1, cur - nums[pos]); } }
1. dfs, 每一步都可以加減,所以從cur0開始,每次dfs都可以±。
顯然 還有更快的方法
public int findTargetSumWays(int[] nums, int S) { int sum = 0; for(int n: nums){ sum += n; } if (S < -sum || S > sum) { return 0;} int[][] dp = new int[nums.length + 1][ 2 * sum + 1]; dp[0][0 + sum] = 1; // 0 + sum means 0, 0 means -sum, check below graph for(int i = 1; i <= nums.length; i++){ for(int j = 0; j < 2 * sum + 1; j++){ if(j + nums[i - 1] < 2 * sum + 1) dp[i][j] += dp[i - 1][j + nums[i - 1]]; if(j - nums[i - 1] >= 0) dp[i][j] += dp[i - 1][j - nums[i - 1]]; } } return dp[nums.length][sum + S]; }
揹包法,普通0/1揹包是選或不選,這個是選它或者選它的負數,所以dp [ i ][ j ] = dp[i-1][j-nums[i-1]] + dp[i-1][j + nums [ i - 1];
dp[ i ][ j ]意思是:為了達到sum j,使用了前i個元素,所以上面的轉移方程顯然(個鬼)
因為j的範圍是 -sum ---- 0 ----sum,所以我們預設dp[ 0 ][ sum]相當於起點0,所以dp[ 0 ][ 0 ] 就代表-sum,dp 【i】【sum+S】就是我們所要求的。