494. 目标和(动态规划,01背包)

给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

 

示例:

输入: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 位整数存下。
通过次数55,907提交次数125,631

 

回溯超时:

class Solution {
public:
    
    void backtrace(int sum,int S,vector<int>& nums,int pos) {
        //符合条件直接添加返回
        if(sum == S && pos == nums.size()){
            result++;
            return;
        }
        if(pos >= nums.size()) return;
         //第i个数取+
        sum += nums[pos];
        backtrace(sum,S,nums,pos+1);
        sum -= nums[pos];
           
        //第i个数取-
        sum -= nums[pos];
        backtrace(sum,S,nums,pos+1);
        sum += nums[pos];
        
    }
    int findTargetSumWays(vector<int>& nums, int S) {
        backtrace(0,S,nums,0);
        return result;
    }
public:
    int result = 0;
};

 

 

dp:要转化成dp

class Solution {
public:
    //dp系列:01背包
    //dp[i][j] = dp[i-1][j-nums[i]] + dp[i-1][j+nums[i]] 这种dp转移相对麻烦一些
    //另一种想法:数组分为正负两部分.   例如1 3 5 为加 sum(P)  2 4为- sum(N)
    //sum(P) + sum(N) = S
    //sum(P) - sum(N) = sum(nums)
    //sum(P) - sum(N) + sum(P) + sum(N) = S + sum(nums) ==> 2*sum(P) = s+sum(nums) ==> sum(P) = (S+sum(nums))/2
    //典型的01背包,从nums中取 k个数使得和P 为(S+sum(nums))/2
    int findTargetSumWays(vector<int>& nums, int S) {
        int n = nums.size();
        int sum = accumulate(nums.begin(),nums.end(),0);
        long s = long(sum) + long(S);
        if(s % 2 || sum < S) return 0;
        vector<vector<int>> dp(n+1,vector<int>(s/2+1,0));
        for(int i=1;i<=n;i++){
            dp[i][0] = 1;
        }
        for(int j=1;j<=s/2;j++){
            dp[0][j] = 0;
        }
        dp[0][0] = 1;
        for(int i=1;i<=n;i++){
       //j从0开始,否则 dp[1][0]对于某些情况失败,[0 0 1] 1中dp[1][0] = 2
for(int j=0;j<=s/2;j++){ if(j >= nums[i-1]) dp[i][j] = dp[i-1][j]+dp[i-1][j-nums[i-1]]; else dp[i][j] = dp[i-1][j]; } } return dp[n][s/2]; } };

 

posted on 2020-12-20 15:14  wsw_seu  阅读(90)  评论(0编辑  收藏  举报

导航