給定一個(gè)非負(fù)整數(shù)數(shù)組,a1, a2, ..., an, 和一個(gè)目標(biāo)數(shù),S。現(xiàn)在你有兩個(gè)符號 + 和 -。對于數(shù)組中的任意一個(gè)整數(shù),你都可以從 + 或 -中選擇一個(gè)符號添加在前面。
返回可以使最終數(shù)組和為目標(biāo)數(shù) S 的所有添加符號的方法數(shù)。
示例 1:
輸入: nums: [1, 1, 1, 1, 1], S: 3
輸出: 5
解釋:
-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
一共有5種方法讓最終目標(biāo)和為3。
想了好久,本想通過計(jì)算出sum(nums)求取總和,再不斷套出答案,但是寫到一半沒有思路了,冥思苦想后看到大佬的思想...
原問題等同于: 找到nums一個(gè)正子集和一個(gè)負(fù)子集,使得總和等于target
我們假設(shè)P是正子集,N是負(fù)子集 例如: 假設(shè)nums = [1, 2, 3, 4, 5],target = 3,一個(gè)可能的解決方案是+1-2+3-4+5 = 3 這里正子集P = [1, 3, 5]和負(fù)子集N = [2, 4]
那么讓我們看看如何將其轉(zhuǎ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)
因此,原來的問題已轉(zhuǎn)化為一個(gè)求子集的和問題: 找到nums的一個(gè)子集 P,使得sum(P) = (target + sum(nums)) / 2
請注意,上面的公式已經(jīng)證明target + sum(nums)必須是偶數(shù),否則輸出為0
根據(jù)大神的方法,我們自然可以得出結(jié)論,我們要找到那個(gè)可以滿足條件的P
class Solution {
public int findTargetSumWays(int[] nums, int S) {
int sum=0;
for (int n : nums)
sum += n;
if(sum<S||(S+sum)%2!=0) return 0;
int p = (S + sum) / 2;
int[] dp=new int [p+1];
dp[0]=1;
for(int num:nums){
for(int i=p;i>=num;i--){
dp[i]=dp[i]+dp[i-num];
}
}
return dp[p];
}
}