Leetcode 494. 目标和(动态规划)

给定一个非负整数数组,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。

想了好久,本想通过计算出sum(nums)求取总和,再不断套出答案,但是写到一半没有思路了,冥思苦想后看到大佬的思想...

原问题等同于: 找到nums一个正子集和一个负子集,使得总和等于target
我们假设P是正子集,N是负子集 例如: 假设nums = [1, 2, 3, 4, 5],target = 3,一个可能的解决方案是+1-2+3-4+5 = 3 这里正子集P = [1, 3, 5]和负子集N = [2, 4]
那么让我们看看如何将其转换为子集求和问题:
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
因此,原来的问题已转化为一个求子集的和问题: 找到nums的一个子集 P,使得sum(P) = (target + sum(nums)) / 2
请注意,上面的公式已经证明target + sum(nums)必须是偶数,否则输出为0

根据大神的方法,我们自然可以得出结论,我们要找到那个可以满足条件的P

class Solution {
    public int findTargetSumWays(int[] nums, int S) {
        int sum=0;
        for (int n : nums)
        sum += n;
        if(sum=num;i--){
              dp[i]=dp[i]+dp[i-num];
          }      
      }  
        return dp[p];
    }
}

执行用时 : 7 ms, 在Target Sum的Java提交中击败了100.00% 的用户

你可能感兴趣的:(Leetcode 494. 目标和(动态规划))