【JS力扣刷题笔记】494.目标和

这是跟着代码随想录的顺序学习算法的第?天。

以下是学习时自己的一些理解与笔记,如有错误欢迎指正与讨论。


494.目标和

参考相关链接:

494. 目标和

代码随想录


笔记

主要思路是将 nums 数组分成两部分来看待,一部分是取 号的,不妨将其总和记为left,另一部分是取 - 号的 right ,将其总和记为 right,考虑最终期望的得到的结果为 target,可得等式 left - right = target

与此同时,我们不难发现等式 left + right = sum ,其中 sum 即为数组总和。

两个等式联立后可得 left = (sum + target)/2 ,这样一来问题就转换成了在 nums 数组中能有多少种方法得到部分和为 left 的组合,这个问题可以用01背包来解决。

01背包中算法实现的一个核心思想为,在初始化了的基础上,考虑本次如果提前放入物品 i,即在背包中提前占用 weight[i] 的容量,再去看此时的剩余容量中可以存放的最大价值为多少。

本题不需要知道最大价值,因为此处最大价值就是目标值 target ,只是需要知道有多少种方法可以达到这个目标值。因此,这里对原始的01背包做一些改动,即在占用提前占用了 nums[i] 容量后,再去看此时的剩余容量中,能够存放满剩余背包的方法有多少种,累加起来。

与此同时,初始化时也需要做出相应的修改,原始的01背包的 dp[j] 表示的是,在 j 容量下,能够装入的最大价值是多少,一开始没有装入的时候,最大价值自然就是 0。此处的01背包的 dp[j] 表示的是在 j 容量下,能够装满的方法有多少种,一开始没有装入的时候,也就只有一种方法装满背包,即装入重量为 0 的,也就是不装。

var findTargetSumWays = function(nums, target) { 
    let sum = 0;
    for(const x of nums) {
        sum += x;
    }
    // 临界条件判断,背包需要达到的目标值必须是整数,target 需要在nums表示范围内
    if((sum + target) % 2 || Math.abs(target) > sum) return 0;
    const half = (sum + target) / 2;
    // dp[j] 表示在 j 容量下,能有多少种方法使得总和达到 j
    let dp = Array(half + 1).fill(0);
    const len = nums.length;
    // 初始化
    dp[0] = 1;
    for(let i = 0; i < len; i++) {
        for(let j = half; j >= nums[i]; j--) {
            // 现在可以装入物品 i,看看占用了nums[i] 容量后还有多少种方法可以达到 j - nums[i]
            dp[j] += dp[j - nums[i]];
        }
    }
    return dp[half];
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值