LeetCode 494. 目标和 javascript步骤+解法

题干:给你一个整数数组 nums 和一个整数 target

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

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例:

输入: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

解题思路:动态规划之01背包

该题主要的切入点就是要将整个表达式拆解成若干正数与若干负数相加。

假设为正数的数字和为:plus ,为负数的数字和则为: nums 之和 - plus

plus - ( nums 之和 - plus ) = target

解方程可得 plus = ( nums 之和 + target ) / 2

令背包的容积为 plus ,物品为nums[i] 来求解能使题目构成01背包问题。

下面就是动态规划的常规五步:

  1. 确定dp数组(dp table)以及下标的含义

    dp[j] 表示填满 j(包括 j)容积(正数和),有 dp[j] 种方法

  2. 确定递推公式

    背包解决求方法数问题 ⇒ 累加法

    由dp数组的含义可得,dp[ j - nums[i] ] 表示不考虑 nums[i] 的方法数,dp[j] 应等于考虑每个nums[i] 的方法数的和,而每个nums[i] 的方法数其实就等于不考虑 nums[i] 的方法数。

    dp[j] += dp[j - nums[i]]

  3. dp数组如何初始化

    dp[0] = 1,意思是装满容量为0的背包,有1种方法,就是装0件物品。

  4. 确定遍历顺序

    for(let i=0; i<nums.length; i++){
    	for(let j=bagWeight; j>=nums[i]; j--){
    		dp[j]+=dp[j-nums[i]]
    	}
    }
    
  5. 举例推导dp数组

        大家可以用示例题自己推导看看dp[j] 的值是否如上文分析的一致。

JavaScript 代码如下:

var findTargetSumWays = function(nums, target) {
    let sum = nums.reduce((a,b)=>a+b)
    if((sum+target) % 2 == 1) return 0;
    let bagWeight = (sum+target)/2;
    let dp = new Array(bagWeight+1).fill(0);
    dp[0] = 1;
    for(let i=0; i<nums.length; i++){
        for(let j=bagWeight; j>=nums[i]; j--){
            dp[j]+=dp[j-nums[i]]
        }
    }
    return dp[bagWeight]
};

注:代码中 Array.reduce() 这个遍历函数用于求和非常有帮助,大家可以去搜搜它的具体用法,这样就不用每次用 for 循环写大段代码啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值