代码随想录|动态规划 416. 分割等和子集

01背包理论

二维:

dp[i][j]

知道dp二维数组中i和j的关系以及含义,i是当前要放的物品,j就是当前背包的容量

在二维数组中,各行的数据是隔离开来的,所以背包容量部分,从后往前和从前往后都是一样的

背包和物品的遍历可以互换

一维:

dp[j]

理解j的含义

容量为j的背包所能得到的最大价值为dp[j]

一维数组每次都是重复利用,而且是有更新的

背包容量部分的遍历只能从后往前遍历,不然会出现不符合01背包的物品只能用一次的规则

只能先遍历物品,在遍历背包

416. 分割等和子集

题目

参考文章

思路:看成价值和重量是相同的

用一维,dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i])

dp只能初始化为0

本题要求集合里能否出现总和为 sum / 2 的子集

如果最大价值是 sum / 2,说明正好被商品装满了

代码:

class Solution {
    public boolean canPartition(int[] nums) {
        //考的就是01背包问题
        if(nums==null||nums.length==0){
            return false;
        }

        int n=nums.length;
        int sum=0;
        for(int num:nums){
            sum+=num;
        }

        if(sum%2!=0){//如果总和除以2的还有余数,就表明这个总和不能平方,故不符合题目条件
            return false;
        }

        int target=sum/2;//由题目知道,要分为两个数组,使得两个数组的和相同,所以先用总和除以2
        int[] dp=new int[target+1];//直接初始化为target个大小,最后因为平方的原因,所以当dp[target]==target时,就表明可以平方。

        for(int i=0;i<n;i++){
            for(int j=target;j>=nums[i];j--){//因为一维数组的原因,所以要倒序遍历背包容量,不然会出现同一个数重复利用的问题,可以自己画图画个数组出来看一下。
                dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        if(dp[target]==target){
            return true;
        }

        return false;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值