494. Target Sum(轉換+dp)
阿新 • • 發佈:2019-02-02
題目:組成目標數有多少種方法?
思路:
舉例說明: 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) 2sum(1,3,5) = target + sum(1,3,5) + sum(2,4) 2sum(P) = target + sum(nums) sum(P) = (target + sum(nums)) / 2 由於target和sum(nums)是固定值,因此原始問題轉化為求解nums中子集的和等於sum(P)的方案個數問題。
如果 sum(nums) 小於 S或者 (sum(nums) + S) % 2 !=0 表示不能組成目標數,返回0。
應用dp解決子集合問題:
dp[y]+=dp[y-num],表示組成數值y的方案數等於原來組成數值y的方案數 + 組成數值y-num的方案數
例如
dp[8] = dp[8] + dp[8-1] (假設陣列為: 1 2 3 4 5)
dp[8] = dp[8] + dp[8-2]
dp[8] = dp[8] + dp[8-3]
dp[8] = dp[8] + dp[8-4]
dp[8] = dp[8] + dp[8-5]
dp程式碼
for(int num : nums)
for (int y=target;y>=num;y--)
dp[y]+=dp[y-num];
完整程式碼:
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for(int num : nums) sum+=num;
if (sum < S || (sum + S) % 2 != 0)
return 0;
int target = (sum+S)>>1 ;
int dp[target+1];
memset(dp,0,sizeof(dp));
dp[0] = 1;
for(int num : nums)
for(int y=target;y>=num;y--)
dp[y]+=dp[y-num];
return dp[target];
}
};