494. 目标和

给你一个非负整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

  • 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例 1:

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 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
+1 + 1 + 1 + 1 - 1 = 3

示例 2:

输入:nums = [1], target = 1
输出:1

提示:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • -1000 <= target <= 1000
class Solution {
public:
    int findTargetSumWays(vector& nums, int target) {
        //抽象为01背包
        //1、每个元素只能拿一次,只有拿或不拿得状态。所以是01背包
        //分为两个集合,一个是正数集合,一个是负数的集合
        // sum + (-neg)->正数  sum + (-neg) + (-neg) = target;
        //  -----------------> neg = (sum - target)/2 

        //所以,neg才是 需要装的背包容量。即只需要解决一个集合的sum
        
        //dp[j];装满j容量的背包,装满一共有d[p]种方法;
        //dp[neg]即为所求

        //递推关系: 假如我有  1   需要dp[4]种 装满dp[5];
        //                   2       dp[3]
        //                   3       dp[2]
        //                   4       dp[1]
        //                   5       dp[0]

        //初始化 ,dp[0] = 1;装满0,不需要装,默认1
        int sum = 0;
        for(int i:nums){
            sum += i;
        }
        if((sum - target) % 2 != 0 || target > sum) return 0;
        int diff = (sum - target)/ 2;
        vectordp(diff+1,0);
        dp[0] = 1;
        for(int i = 0;i < nums.size();i++){
            for(int j = diff;j >= nums[i];j--){
                dp[j] += dp[j-nums[i]]; 
            }
        }
        return dp[diff];
    }
};

你可能感兴趣的:(leetcode练习,算法,数据结构,c++,动态规划)