[LeetCode] 494. Target Sum
阿新 • • 發佈:2018-12-18
題目
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.
題目大意
取 陣列 nums 中 的每個元素 或 其負數,求所有和為S 的組合數。
思路
該問題轉換為 Subset Sum 問題,從而使用 0-1 揹包的方法來求解。
可以將這組數看成兩部分,P 和 N,其中 P 使用正號,N 使用負號,有以下推導:
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
因此只要找到一個子集,令它們都取正號,並且和等於 (target + sum(nums))/2,就證明存在解。
具體解法:
揹包問題,動態規劃:
狀態int dp[i][j] :陣列中,前i個數的subSum為j的組合個數 。
初始化狀態:dp[0][0] =0, 前0個數的subSum 定為 0 組合個數為1。
狀態轉移方程: 近似揹包問題的狀態轉移方程。
for(int j = 0;j <= target;j++){
if(j<nums[i-1])
dp[i][j] = dp[i-1][j];
else
dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]];
}
code:
class Solution {
public int findTargetSumWays(int[] nums, int S) {
int sum = 0;
for(int num:nums)
sum += num;
if(sum < S || (sum+S)%2==1)
return 0;
int target = (sum+S)/2;
int[][] dp = new int[nums.length+1][target+1];
System.out.println(target);
dp[0][0] = 1;
for(int i = 1;i <= nums.length;i++)
for(int j = 0;j <= target;j++){
if(j<nums[i-1])
dp[i][j] = dp[i-1][j];
else
dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]];
}
return dp[nums.length][target];
}
}
由於dp[i][j] 只用到 dp[i-1][j],所以 可以使用一維。
class Solution {
public int findTargetSumWays(int[] nums, int S) {
int sum = 0;
for(int num:nums)
sum += num;
if(sum < S || (sum+S)%2==1)
return 0;
int target = (sum+S)/2;
int[] dp = new int[target+1];
dp[0] = 1;
for(int num:nums)
for(int j = target;j >= num;j--)
dp[j] = dp[j] + dp[j-num];
return dp[target];
}
}