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

HOT100题打卡第26天——动态规划

中午好,继续来写今天的题

上题目

416. 分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

分析题目

解题思路

将数组分成两个子集,子集的元素和相等,其实我们就可以理解为,每个子集的元素和都等于数组的元素和除以2

我们把子集的元素和用target表示,数组的元素和用sum表示,那么target=sum/2

因为两个子集的元素和是相等的,因此只需要判断能否凑成一个和为target的子数组,一个满足另一个也一定满足

但是如果sum是奇数,那就不可能分成两个元素和相等的子数组

dp数组含义

这道题用到的是boolean型数组

数组下标索引表示当前需要凑的目标值,dp[ i ]就表示能否凑成和为 i 的子数组

只需要判断到target,所以dp数组长度=target+1(target就是下标i,加1是因为还有0索引)

数组初始化

因为一开始并不确定是否能凑成和为 i 的子数组,所以我们一开始把dp数组中的每一个元素的值都初始化为false

然后因为和为0的子数组始终能凑成,就是空集,所以dp[0]=true;

循环遍历

首先我们是从nums数组中获取元素来凑成目标值,所以先遍历nums数组

内层循环遍历的是dp数组,因为目标值是targe(dp数组中索引=目标值),所以最大只需遍历到target,

状态转移逻辑:

若不选当前元素nums[i]时,dp[j]已经为true(能凑出j),则保持true; 

若选当前当前元素nums[i]时,之前能凑出j - nums[i](即dp[j - nums[i]]为true)

 则加上当前元素后就能凑出j,因此dp[j]更新为true。

内层为什么反向遍历

用例一来解释:

总和 sum=22target=11dp 数组索引 0~11(dp[j] 表示能否凑出和为 j 的子集)。

初始 dp = [T, F, F, F, F, F, F, F, F, F, F, F](仅 dp[0]=T,空集)。

如果是正序遍历(j从1到11

逐个更新 j=1→2→...→11,每步用当前更新后的 dp 状态:

j=1dp[1] = F || dp[0](T)→ T(正确,用 1 凑 1)→ dp[1]=T

j=2dp[2] = F || dp[1](刚更的T)→ T(错误!此时只有 1 个 1,却凑出 2,相当于用了两次 1)

j=3dp[3] = F || dp[2](刚更的T)→ T(错误,1+1+1=3,用了三次 1)

... 以此类推,j=4——11 都会被错误更新为 T(因为每次都用前一步更新的小 j

因此需要倒序遍历,因为dp数组初始值都是false,倒着遍历时不会受到前面结果的影响


ok,分析到这里我们来看代码

代码

class Solution {public boolean canPartition(int[] nums) {//将数组分成两个子集,并且两个子集的元素和相等,就是把数组平均分成了两份//求出数组的总和sum,得到sum/2,判断int sum = 0;for (int i = 0; i < nums.length; i++) {sum += nums[i];}//如果sum和是奇数说明不能平均分成两个子数组,直接返回falseif (sum % 2 == 1) {return false;}//我们只需要判断能否凑出target,因为sum分成两个等份,target是其中一份,target满足则另一半一定满足int target = sum / 2;//dp数组的含义:下标i表示所有target所有可能的取值,dp[i]表示和为i的子集是否存在,长度加1是为了放索引0//只需要判断0——target位置boolean[] dp = new boolean[target + 1];/*        //初始化数组,全设为false,因为暂时还不确定,但是boolean数组初始默认就是false,无需手动赋值for (int i = 0; i < dp.length; i++) {dp[i] = false;}*///dp[0]=true;和为0的子数组就是空集dp[0] = true;//遍历nums数组中的每一个数for (int i = 0; i < nums.length; i++) {//内层循环只需遍历到target,因为后面的数都大于target不满足条件for (int j = target; j >= nums[i]; j--) {// 状态转移逻辑:// 若不选当前元素nums[i]时,dp[j]已经为true(能凑出j),则保持true;// 若选当前当前元素nums[i]时,之前能凑出j - nums[i](即dp[j - nums[i]]为true),// 则加上当前元素后就能凑出j,因此dp[j]更新为true。if (dp[j] || dp[j - nums[i]]) {dp[j] = true;}}}return dp[target];}
}

好了,那今天的代码就写到这里了,我们明天见!

http://www.dtcms.com/a/561209.html

相关文章:

  • 第五章 二项式系数
  • 制作网站语言网络营销方法有什么
  • 合肥网站建站推广从零开始做电影网站
  • 电商Web 渗透测试小小清单
  • 做信息流推广需要建立网站么最基本的网站设计
  • 基于双向时序卷积网络与门控循环单元(BiTCN-GRU)混合模型的时间序列预测MATLAB代码
  • DevOps(devops/k8s/docker/Linux)学习笔记-2
  • 三点水网站建设wordpress wp-polls
  • 用数据照亮成长之路:PandaCoder Git 统计工具窗口
  • FPGA的LVDS接口电压
  • 【每天一个AI小知识】:什么是Embedding?
  • 南昌网站排名优化免费提供空间的网站
  • 三种服务生命周期
  • Mybatis的添加和修改功能
  • Linux 安全文件传输完全指南:sftp 与 scp 的深度解析引言
  • Mysql基础3
  • 上海cms网站建设珠海网站建设 科速
  • 有没有可以做游戏的网站电商网课教材
  • 【自然语言处理】生成式语言模型GPT复现详细技术方案
  • Qt 打开文件列表选择文件,实现拖拽方式打开文件,拖拽加载
  • 网站搭建徐州百度网络搭建专做婚礼logo的网站
  • macOS 上获取调试版
  • 奉加微PHY6230软件三:自定义MAC和ll_set_ble_mac_addr不能屏蔽
  • 模型推理如何利用非前缀缓存
  • 网站建设方面的论文重庆网站制作工作室
  • 优化学校网站建设方案wordpress+免备案空间
  • Linux系统之----UDP、TCP详解
  • TcpConnection
  • 选对模型、搭好架构:企业如何构建高精准RAG知识库
  • 广东网站设计公司价格软件商城app下载