力扣【416. 分割等和子集】详细Java题解(背包问题)

首先我们可以求出数组和,当我们找到一个子集中元素的和为数组和的一半 时,该就说明可以分割等和子集。

对于该问题我们可以转换成背包问题,求 数组里的元素 装入 数组和的一半大小的背包 能取得的最大值。

然后注意可以剪枝的地方。

代码:

csharp 复制代码
class Solution {
    public boolean canPartition(int[] nums) {
        //计算数组的和
        int sum =0;
        for(int num:nums) sum += num;
        if(sum%2 != 0) return false; //如果和为奇数,那就不符合
        sum /= 2;
        int[][] dp = new int[nums.length+1][sum+1]; //dp[i][j]表示遍历到前i个物品时,j容量背包能转的最大值
        //第0行就是还没有物品加入计算,初始化为0
        for(int i=0;i<sum+1;i++){
            dp[0][i] = 0; 
        }
        //开始动规计算
        for(int i=1;i<=nums.length;i++){
            for(int j=1;j<=sum;j++){
                if(nums[i-1] <= j) dp[i][j] = Math.max(nums[i-1] + dp[i-1][j-nums[i-1]],dp[i-1][j]);
                else dp[i][j] = dp[i-1][j];
            }
            if(dp[i][sum] == sum) return true; //剪枝
        }
        //结果判断
        if(dp[nums.length][sum] == sum){
            return true;
        }
        return false;
    }
}

不过我们其实可以用一维数组来做,因为我们的每次迭代其实只用到了dp数组的上一行。那我们可以用一个数组来进行滚动,不过遍历顺序得从后往前,因为我们迭代后面的物品时需要用到前面物品的值,且当容量大于当前遍历的物品时才迭代。

这样我们的代码更简洁且时间复杂度和空间复杂度都有改善。

csharp 复制代码
class Solution {
    public boolean canPartition(int[] nums) {
        //计算数组的和
        int sum =0;
        for(int num:nums) sum += num;
        if(sum%2 != 0) return false; //如果和为奇数,那就不符合
        sum /= 2;
        int[] dp = new int[sum+1]; 
        //第0行就是还没有物品加入计算,初始化为0
        for(int i=0;i<sum+1;i++){
            dp[i] = 0; 
        }
        //开始动规计算
        for(int i=1;i<=nums.length;i++){
            for(int j=sum;j>=nums[i-1];j--){
                dp[j] = Math.max(nums[i-1] + dp[j-nums[i-1]],dp[j]);
                if(j==sum && dp[j] == sum) return true; //剪枝
            }
        }
        return false;
    }
}
相关推荐
Jerry&Grj17 分钟前
SpringBoot埋点功能技术实现方案深度解析:架构设计、性能优化与扩展性实践
java·微服务·性能优化·springboot·架构设计·埋点技术
没有bug.的程序员23 分钟前
Redis Stream:轻量级消息队列深度解析
java·数据库·chrome·redis·消息队列
沐怡旸42 分钟前
【算法--链表】114.二叉树展开为链表--通俗讲解
算法·面试
用户81607918333343 分钟前
告别“魔法”:包你解决 Gradle 的下载慢问题
java
一只懒洋洋1 小时前
K-meas 聚类、KNN算法、决策树、随机森林
算法·决策树·聚类
当归10241 小时前
SQL Server死锁排查实战指南
java·服务器·网络
echoyu.1 小时前
消息队列-初识kafka
java·分布式·后端·spring cloud·中间件·架构·kafka
little_xianzhong2 小时前
关于对逾期提醒的定时任务~改进完善
java·数据库·spring boot·spring·mybatis
百锦再2 小时前
脚本语言的大浪淘沙或百花争艳
java·开发语言·人工智能·python·django·virtualenv·pygame
小猪咪piggy2 小时前
【JavaEE】(23) 综合练习--博客系统
java·数据库·java-ee