【0-1背包】例题之LeetCode 目标和

(一)、题目描述

(二)、思路

我先来解释一下这道题,就是给定一个数组,从这个数组中挑选一部分数出来相加,减去剩下的数的和能达到题目所给的「target」。

所以我们设数组的总数和为「sum」,挑选出来的数字和为「left」,剩下的数字和为「right」。由题得:left - right =target。right = sum - left。所以 left - (sum - left) =target。                            left = (sum + target) / 2。

将这道题转化为【背包问题】应该是:

我们背包容量为 left,每个数组元素的「价值」与「重量」都是其数值大小,求我们能否装满背包。

(三)、解答方法

我们要求组成 left 的组合,所以每个数只能使用一次,我们应该直接想到【0-1背包】。那么我们可以直接套用【0-1背包】问题的方法。

如果还不了解【0-1背包】问题的小伙伴可以点击这【0-1背包】和【完全背包】详解学习一下【0-1背包】问题。

1.确定dp数组及下标的含义:

 【0-1背包】中,dp[j] 表示: 容量为j的背包,所背的物品价值最大可以为dp[j]。                               本题中每一个元素的数值既是重量,也是价值。套到本题,dp[j] 表示:凑成背包容量为 j 总共有多少种方法

2.确定递推公式

【01背包】的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。

所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

3.初始化dp数组:

从dp[j]的定义来看,首先dp[0]一定是0,其次其他位置也要初始化为0。

这样才能让dp数组在递推的过程中取得最大的价值,而不是被初始值覆盖了。

(四)、代码

        

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum=0;
        for(int i=0;i<nums.size();i++)
        {
            sum+=nums[i];
        }
        if(abs(target)>sum) return 0;
        if((target+sum)%2==1)
            return 0;
        int left=(target+sum)/2;
        vector<int> dp(left+1,0);
        dp[0]=1;
        for(int i=0;i<nums.size();i++)
        {
            for(int j=left; j >= nums[i]; j--)
            {
                dp[j]+=dp[j-nums[i]];
            }
        }
        return dp[left];
    }
};

总结

这就是本期博客的全部内容了,如果还想了解更多有关【0-1背包】类型的问题请看我的【动态规划之0-1背包】专栏。

谢谢观看,如果觉得博主还不错的话请点个赞和关注再走吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值