leetcode 494. 目标和 (01 背包

。。最近背包问题做得好崩溃

这题的解法和  分割子集、石头 差不多

当给nums中的数字加上符号以后,可以分成两个集合

这里的集合 P  和 集合 N 都是正数,因为只是计算了数值!

        a. 正号 的数字集合 P

        b. 负号 的数字集合 N

所以就有以下公式

sum(P) + sum(N) = sum(nums)

sum(P) -  sum(N) = target

所以

sum(P)  = (target + sum(nums)) / 2

所以

需要求出和为  (target + sum(nums)) / 2 的方案有多少个

1.dp 数组的含义

        dp [ j ]

        下标:和为 j

        值: 和为 j 的方案有多少个

2.递推公式

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

        不选i : dp [ j ]

        选i :dp [ j - nums[ i ] ]

        意思是,如果选择了 i , 则 剩下要组成和为j - nums [ i ] 的方案数就等于dp[ j - nums [ i ] ]

3.初始化

        dp [ 0 ] = 1

        这有点绕。。就当作是 和 为0 的方式 只有一种。

        例如:集合  [ 0 ] target = 0 , 此时就只有一种方法

4. 遍历顺序

        和之前一样,物品正序,背包倒叙

注意:

        有两个判断

        如果不能整除 2 , 就说明没有找到 pos,因为是元素都是整数

        如果target 的绝对值大于 sum,说明不可能找到方案

图源力扣官方题解

if((sum + target) % 2 == 1) return 0;
if(abs(target) > sum) return 0;
class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {

        int sum = 0;
        for(int a : nums)
        {
            sum += a;
        }
        int pos = (target + sum) / 2;
        if((sum + target) % 2 == 1) return 0;
        // 要加绝对值
        if(abs(target) > sum) return 0;

        vector<int> dp(pos + 1, 0);

        dp[0] = 1;

        for(int i = 0; i < nums.size(); i++)
        {
            for(int j = pos; j >= nums[i]; j--)
                dp[j] = dp[j] + dp[j - nums[i]];

        }
        
        return dp[pos];

    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值