当前位置: 首页 > article >正文

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

首先我们可以求出数组和,当我们找到一个子集中元素的和为数组和的一半时,该就说明可以分割等和子集。
对于该问题我们可以转换成背包问题,求 数组里的元素 装入 数组和的一半大小的背包 能取得的最大值。
然后注意可以剪枝的地方。

代码:

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数组的上一行。那我们可以用一个数组来进行滚动,不过遍历顺序得从后往前,因为我们迭代后面的物品时需要用到前面物品的值,且当容量大于当前遍历的物品时才迭代。
这样我们的代码更简洁且时间复杂度和空间复杂度都有改善。

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;
    }
}

http://www.kler.cn/a/526079.html

相关文章:

  • C++中常用的排序方法之——冒泡排序
  • 《智能家居“孤岛危机”:设备孤立如何拖垮系统优化后腿》
  • 索引02之正确建立和使用索引
  • 572. 另一棵树的子树
  • 1.文件 标准IO库
  • JxBrowser 8.2.2 版本发布啦!
  • momask-codes 部署踩坑笔记
  • 列表(列表是什么)
  • 【Qt】信号和槽简介
  • vue相关的页面和js编写
  • Fork/Join框架_任务分解与并行执行
  • 智慧园区管理平台实现智能整合提升企业运营模式与管理效率
  • 记录一次Sqoop从MySQL导入数据到Hive问题的排查经过
  • 使用Swiper构建运营推荐位
  • 【蓝桥杯省赛真题02】C++猫吃鱼 第十届蓝桥杯青少年创意编程大赛 算法思维 C++编程省赛真题解
  • JAVASE入门十二脚-file,IO流
  • 【DeepSeek-V3】AI Model Evaluation Framework and index schedule AI模型能力评价指标及对比
  • 395. 至少有K个重复字符的最长子串
  • continuous batching、chunked-prefill相关概念
  • springboot3 集成 knife4j(接口文档)