Bootstrap

LeetCode:494.目标和

跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的!
代码随想录

LeetCode: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

  • 0-1背包求的是背包容量为j能装的最大价值
  • 分割等和子集求的是能否装满容量为target的背包
  • 最后一块石头的重量求的是容量为target的背包能装的最大重量是多少
  • 目标和求的是容量为target的背包装满有多少种方式,递推公式:dp[j] += dp[j - nums[i]]
  • 本题中,设所有添加+符号的和为left,所有添加-符号的和为right,有left + right = sumleft - right = target,则left = (sum + target) / 2
  • dp[j]含义:装满容量为j的背包的方法数有dp[j]
  • 如果不选nums[i]dp[j] = dp[j],如果选nums[i]时,dp[j] = dp[j -num[i], 所以递推公式:dp[j] = dp[j] + dp[j - nums[i]] ,即:dp[j] += dp[j - nums[i]]
  • 初始化:装满容量为0的背包的方法数有1中,所以dp[0] = 1
	public int findTargetSumWays(int[] nums, int target) {
        int sum = Arrays.stream(nums).sum();
        // 如果target的绝对值大于sum,则说明目标和一定不会为target的
        if (Math.abs(target) > sum)
            return 0;
        if ((target + sum) % 2 != 0)
            return 0;
        int bagSize = (target + sum) / 2;
        int[] dp = new int[bagSize + 1];
        dp[0] = 1;
        for (int i = 0; i < nums.length; i++) {
            for (int j = bagSize; j >= nums[i]; j--) {
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[bagSize];
    }
;