416. 分割等和子集

https://leetcode-cn.com/problems/partition-equal-subset-sum/
这道题要我们判断这个数组能否分割为2个子集,使得两个子集的元素和相等
因此,只要找到元素和为总和的一半的子集,就找到了两个子集

因为元素和我们只能用一次,所以在这道题中我们需要使用01背包的思想
我们可以确定的条件:
1.背包的大小为所有元素之和的一半
2.背包需要放入的商品的价值为元素的数值,重量也是
3.背包正好装满的时候,说明找到了总和为元素之和一半的子集
4.背包中每一个元素不可重复放入
接着,我们就可以按照动归的规则写题目了
1.dp数组及下标的含义,dp[i]表示,容量为i的背包,可以容纳的物品价值最大为dp[i],在本题中,可以认为,dp[i]表示背包的总容量是i,所背的物品价值最大为dp[i]
2.确定递推公式
01背包的递推公式为dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
在本题中,递推公式为dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
3.dp数组如何初始化
如果题目数据为正数,则初值为0,否则取负无穷
这样可以让dp数组在赋值的过程中取最大价值,不会被初值覆盖
在本题中初值赋0就可以了
4.确定遍历顺序
如果是一维数组,那么物品遍历的for循环放在外侧,遍历背包的for循环放在内侧,且内侧for循环倒叙遍历
5.举例推动dp数组

以下为题目代码

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;
        vector<int>dp(10001,0);
        for(int i=0;i<nums.size();i++)sum+=nums[i];
        if(sum&1==1)return false;//如果sum为奇数,那么不可能
        int target=sum/2;
        for(int i=0;i<nums.size();i++)
        {
            for(int j=target;j>=nums[i];j--)//背包容量遍历
            {
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        if(dp[target]==target)return true;
        else return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值