力扣【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;
    }
}
相关推荐
木易 士心5 分钟前
Spring AI 核心架构解析:构建企业级 AI 应用的 Java 新范式
java·spring
CoovallyAIHub13 分钟前
全球OCR新标杆!百度0.9B小模型斩获四项SOTA,读懂复杂文档像人一样自然
深度学习·算法·计算机视觉
61900833615 分钟前
linux 安装jdk
java·linux·运维
weixin_3776348416 分钟前
【强化学习】RLMT强制 CoT提升训练效果
人工智能·算法·机器学习
懂得节能嘛.18 分钟前
【动态配置中心】Java+Redis构建动态配置中心
java·开发语言·redis
专注于大数据技术栈19 分钟前
Java中JDK、JRE、JVM概念
java·开发语言·jvm
YuanlongWang23 分钟前
C# 基础——值类型与引用类型的本质区别
java·jvm·c#
拾光Ծ41 分钟前
【C++高阶数据结构】红黑树
数据结构·算法
Kay_Liang1 小时前
大语言模型如何精准调用函数—— Function Calling 系统笔记
java·大数据·spring boot·笔记·ai·langchain·tools
Qiuner1 小时前
《掰开揉碎讲编程-长篇》重生之哈希表易如放掌
数据结构·算法·leetcode·力扣·哈希算法·哈希·一文读懂