9.8分割等和子集(LC416-M)

算法:

可以转换为背包问题:

一个商品如果可以重复多次放入是完全背包,而只能放入一次是01背包,写法还是不一样的。

要明确本题中我们要使用的是01背包,因为元素我们只能用一次。

只有确定了如下四点,才能把01背包问题套到本题上来。

  • 背包的体积为sum / 2
  • 背包要放入的商品:集合里的元素。重量为 元素的数值,价值也为元素的数值
  • 背包如果正好装满,说明找到了总和为 sum / 2 的子集。
  • 背包中每一个元素不可重复放入。

动规五步曲:

1.确定dp数组及其下标:

01背包中,dp[j] 表示: 容量为j的背包,所背的物品价值最大可以为dp[j]。

本题:dp[j]表示 背包总容量(所能装的总重量)是j,放进物品后,背的最大重量为dp[j]

2.确定递推公式:

01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。

所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

3.dp初始化:

从dp[j]的定义来看,dp[0]一定是0。

如果题目给的价值都是正整数那么非0下标都初始化为0就可以了,如果题目给的价值有负数,那么非0下标就要初始化为负无穷。

这样才能让dp数组在递推的过程中取得最大的价值,而不是被初始值覆盖了

4.确定遍历顺序:

01背包如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!

// 开始 01背包
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]);}
}

5.举例推导dp

dp[j]的数值一定是小于等于j的。

如果dp[j] == j 说明,集合中的子集总和正好可以凑成总和j,理解这一点很重要。

dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])

    • `dp` 数组初始化为 `[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`(长度为 `target + 1`,即 12)。
    • `i = 0``nums[0] = 1`
      • 内层循环从 `target`(11)到 `nums[0]`(1):
        • `j = 11``dp[11] = Math.max(0, dp[11 - 1] + 1) = 1`
        • `j = 10``dp[10] = Math.max(0, dp[10 - 1] + 1) = 1`
        • `j = 5``dp[5] = Math.max(0, dp[5 - 1] + 1) = 1`
        • `j = 1``dp[1] = Math.max(0, dp[1 - 1] + 1) = 1`
    • `i = 1``nums[1] = 5`
      • 内层循环从 `target`(11)到 `nums[1]`(5):
        • `j = 11``dp[11] = Math.max(1, dp[11 - 5] + 5) = 6`
        • `j = 10``dp[10] = Math.max(1, dp[10 - 5] + 5) = 6`
        • `j = 5``dp[5] = Math.max(1, dp[5 - 5] + 5) = 6`
        • `j = 1``dp[1] = Math.max(1, dp[1 - 5] + 5) = 5`
    • `i = 2``nums[2] = 11`
      • 内层循环从 `target`(11)到 `nums[2]`(11):
        • `j = 11``dp[11] = Math.max(6, dp[11 - 11] + 11) = 11`
        • `j = 10``dp[10] = Math.max(6, dp[10 - 11] + 11) = 11`
        • `j = 5``dp[5] = Math.max(6, dp[5 - 11] + 11) = 11`
        • `j = 1``dp[1] = Math.max(6, dp[1 - 11] + 11) = 11`
    • `i = 3``nums[3] = 5`
      • 内层循环从 `target`(11)到 `nums[3]`(5):
        • `j = 11``dp[11] = Math.max(11, dp[11 - 5] + 5) = 11`
        • `j = 10``dp[10] = Math.max(11, dp[10 - 5] + 5) = 11`
        • `j = 5``dp[5] = Math.max(11, dp[5 - 5] + 5) = 11`
        • `j = 1``dp[1] = Math.max(11, dp[1 - 5] + 5) = 11`

由于在 `i = 3` 时 `dp[target] == target`,所以最终返回 `true`

正确代码:

class Solution {public boolean canPartition(int[] nums) {int sum = 0;//求和for(int a=0; a<nums.length; a++){sum += nums[a];}//若sum为奇数,无法等分if (sum % 2 != 0) return false;//求targetint target = sum/2;int[] dp = new int[target+1];//dp初始化,所有值都为0(就算不初始化,java也会自动把int数组初始化为0)for (int i=0; i<dp.length;i++){dp[i]=0;}for(int i = 0; i<nums.length; i++){for(int j=target; j>=nums[i]; j--){dp[j] = Math.max(dp[j], dp[j-nums[i]]+nums[i]);}}//若背包装满了,return truereturn dp[target] == target;}}

注意:

1.使用sum时,要将sum初始化:int sum = 0;

2.求target之前,要考虑sum能不能被等分

3.dp数组的长度为target+1

4.for循环时j>=nums[i]

大于等于!

 `j>=nums[i]` 时,考虑的是包括当前物品的情况,因为想要确保当前物品可以放入背包中。

如果使用 `j>nums[i]`,那么就会漏掉考虑将当前物品放入背包的情况,因为此时不包括当前物品的情况也会被考虑到。

5.函数的返回值是bool,所以最后return dp[target] == target;

6.如果将数组 `dp` 的初始化部分注释掉,代码仍然能够正常工作

Java中对于未显式初始化的数组,会自动将数组的元素初始化为默认值。

对于基本数据类型 `int`,其默认值为0。因此,当创建一个 `int` 类型的数组时,如果没有显式地对数组进行初始化,Java会自动将数组的元素初始化为0。

时间空间复杂度:

  • 时间复杂度:O(n^2)

  • 空间复杂度:O(n),虽然dp数组大小为一个常数,但是大常数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/506402.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字化导师坚鹏:证券公司数字化运营三步曲之认知、行动、结果

证券公司数字化运营三步曲之认知、行动、结果 课程背景&#xff1a; 很多证券公司都在开展数字化运营工作&#xff0c;目前存在以下问题急需解决&#xff1a; 不清楚证券公司数字化运营包括哪些关键工作&#xff1f; 不清楚证券公司数字化运营工作的核心方法论&#xff1f…

2024年盘点Mac上的那些强大好用的系统清理软件

现如今MacOS上的系统维护清理软件层出不穷&#xff0c;选择一款合适的系统工具是我们的当务之急&#xff0c;下边就带你盘点一下Mac上的那些优秀好用的系统清理软件&#xff0c;看看哪款你最喜欢吧&#xff01; ​ 1、App Cleaner & Uninstaller Pro App Cleaner mac版是…

Docker知识点总结

二、Docker基本命令&#xff1a; Docker支持CentOs 6 及以后的版本; CentOs7系统可以直接通过yum进行安装&#xff0c;安装前可以 1、查看一下系统是否已经安装了Docker: yum list installed | grep docker 2、安装docker&#xff1a; yum install docker -y -y 表示自动确认…

【精华】麻省理工学院MIT技术双月刊(Bimonthly MIT Technology Review)2024年3/4月刊荐书 Book reviews

本期内容概览见博客&#xff1a;2024年3/4月刊内容概览 Book Reviews 1. Read Write Own: Building the Next Era of the Internet By Chris Dixon (Random House, 2024) With the demise of Twitter, many have advocated for a decentralized alternative for social medi…

gofly接口入参验证使用介绍

接口传入的参数做相关性质验证是开发中较为常用&#xff0c;gofly框架内置校验工具&#xff0c;提供开发效率&#xff0c;开发接口简单调用即可实现验证&#xff0c;下面介绍gofly框架数据验证设计思路及使用方法。 gofly框架提供了功能强大、使用便捷、灵活易扩展的数据/表单…

笨办法学 Python3 第五版(预览)(一)

原文&#xff1a;Learn Python the Hard Way, 5th Edition (Early Release) 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 模块 1&#xff1a;Python 入门 练习 0&#xff1a;准备工作 这个练习没有代码。这只是你完成的练习&#xff0c;让你的计算机运行 Python。…

flurl升级之后没有FlurlNewtonsoftJsonSerializer

新建NewtonsoftJsonSerializer.cs /// <summary> /// ISerializer implementation based on Newtonsoft.Json. /// Default serializer used in calls to GetJsonAsync, PostJsonAsync, etc. /// </summary> public class NewtonsoftJsonSerializer : IJsonSerial…

【PDF技巧】网上下载的pdf文件怎么才能编辑

不知道大家有没有遇到过网上下载的PDF文件不能编辑的情况&#xff0c;今天我们来详细了解一下导致无法编辑的原因即解决方法有哪些。 第一种原因&#xff1a;PDF文件中的内容是否是图片&#xff0c;如果确认是图片文件&#xff0c;那么我们想要编辑&#xff0c;就可以先使用PD…

程序员把年终复盘交给AI-复利再投

1.复盘重要但不紧急 在做年末总结时&#xff0c;复盘&#xff0c;改进计划&#xff0c;这是我觉得最重要的一段时间&#xff0c;它不紧急&#xff0c;但是极其重要。 年底的复盘就像把今年的收获&#xff0c;转移到一个复利账户里&#xff0c;提取的经验越多&#xff0c;来年…

论文阅读_代码生成模型_CodeLlama

英文名称: Code Llama: Open Foundation Models for Code 中文名称: Code Llama&#xff1a;开放基础代码模型 链接: https://arxiv.org/abs/2308.12950 代码: https://github.com/facebookresearch/codellama 作者: Baptiste Rozire, Jonas Gehring, Fabian Gloeckle, Sten So…

USLE模型-P因子的计算

首先需要下载土地利用类型数据集&#xff0c;查看我的相关文章 对于已有的10种土地类型代码&#xff0c;需要按水土保持措施P值表进行重分类。 10是耕地&#xff0c;且庆阳市坡度10-15度左右&#xff0c;所以赋给了3&#xff08;最好再下个DEM计算一下&#xff0c;这里就统一用…

ue4.27 发现 getRandomReachedLocation 返回 false

把这个玩意儿删掉&#xff0c;重启工程&#xff0c;即可 如果还不行 保证运动物体在 volum 内部&#xff0c;也就是绿色范围内确保 project setting 里面的 navigation system 中 auto create navigation data 是打开的(看到过博客说关掉&#xff0c;不知道为啥) 如果还不行&…