LeetCode-【動態規劃】-目標和
阿新 • • 發佈:2018-12-31
給定一個非負整數陣列,a1, a2, ..., an, 和一個目標數,S。現在你有兩個符號 +
和 -
。對於陣列中的任意一個整數,你都可以從 +
或 -
中選擇一個符號新增在前面。
返回可以使最終陣列和為目標數 S 的所有新增符號的方法數。
示例 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種方法讓最終目標和為3。
注意:
- 陣列的長度不會超過20,並且陣列中的值全為正數。
- 初始的陣列的和不會超過1000。
- 保證返回的最終結果為32位整數。
題解:舉例說明: nums = {1,2,3,4,5}, target=3, 一種可行的方案是+1-2+3-4+5 = 3 該方案中陣列元素可以分為兩組,一組是數字符號為正(P={1,3,5}),另一組數字符號為負(N={2,4})
因此: sum(1,3,5) - sum(2,4) = target
sum(1,3,5) - sum(2,4) + sum(1,3,5) + sum(2,4) = target + sum(1,3,5) + sum(2,4)
sum(1,3,5) = target + sum(1,3,5) + sum(2,4)
sum(P) = target + sum(nums)
sum(P) = (target + sum(nums)) / 2
由於target和sum(nums)是固定值,因此原始問題轉化為求解nums中子集的和等於sum(P)的方案個數問題
接著這個分析,求陣列子集和的問題參考本部落格中的文章https://blog.csdn.net/zw159357/article/details/82805282,但本題基於子集和改變了一個條件,這裡求的是能組成子集和的情況有多少種,所以考慮怎樣描述這個未知量,設dp[i]表示數字和為i時對應的對應的數目,它的前一種狀態可表示為dp[i-nums[j]],這裡減去nums[j]的意思是減去當前數字對應的解,dp[i]相應就表示加上當前數字的最優解,最後i對應的值應該是sum(P);
class Solution {
public int findTargetSumWays(int[] nums, int s) {
int sum = 0;
int n=nums.length;
for(int i=0;i<n;i++)
sum+=nums[i];
if(s>sum||(sum+s)%2!=0)
return 0;
int t=(sum+s)/2;
int[] dp=new int[t+1];
dp[0]=1;
for(int i=0;i<n;i++){
for(int j=t;j>=nums[i];j--){
dp[j]+=dp[j-nums[i]];
}
}
return dp[t];
}
}