动态规划LeetCode-416.分割等和子集

news/2025/2/14 4:30:35/

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

示例 1:

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

示例 2:

输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100

01背包问题
背包问题,大家都知道,有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
01背包一维滚动数组递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

本题如何转换到01背包问题是关键,我们想一想,题目说分割两个等和子集,那只需要是sum/2得到一个子集的体积,这个sum/2得到的相当于就是一个背包,这个背包体积是sum/2,看nums里面能否把这个背包体积装满,如果能装满,即可以分割等和子集。对应01背包问题,这题注意的点是背包要放入的商品(集合里的元素)重量为元素的数值,价值也为元素的数值,其次背包中每一个元素是不可重复放入。动规五部曲(dp含义、递推公式、初始化、遍历顺序、打印数组)

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

递推公式:本题中每一个元素的数值既是重量,也是价值。所以
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

初始化:背包容量为j=0,物品最大价值为dp[0]=0这个好理解,那其他下标初始化也为0是为什么呢,因为dp数组在递推的过程中取得最大的价值,把下标初始成负无穷小,就不会被初始值覆盖,这里初始为0即可,也是一样的。

遍历顺序:
这里是用一维滚动数组来解决,所以物品遍历的for循环放在外层,遍历背包的for循环放在内层,然后题目说物品i只能放一次,所以且内层for循环倒序遍历!
因为倒序遍历是为了保证物品i只被放入一次!。但如果一旦正序遍历了,那么物品0就会被重复加入多次!

打印数组:当遇到疑惑或者提交错误时,打印数组出来比较快速的看看哪一步有错。

以下是我在力扣c语言提交的代码,仅供参考:
一维滚动数组:

bool canPartition(int* nums, int numsSize) {//给出容量和数值大小范围,求的还是一半,所以数组大小为200*100/2+1int dp[10001]={0};int sum = 0;int target = 0;for(int i = 0;i<numsSize;i++){sum+= nums[i];}//如果总和为偶数说明可以分割等和子集,反之if(sum % 2 == 0){target = sum / 2;}else if(sum % 2 != 0){return false;}//初始化memset(dp,0,sizeof(dp));dp[0] = 0;//先遍历物品for(int i = 0;i<numsSize;i++){//再遍历背包,且是倒序遍历,保证物品i只被放入一次!for(int j = target;j>=nums[i];j--){//01背包递推公式dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);//本题中每一个元素的数值既是重量,也是价值dp[j] = dp[j] > dp[j-nums[i]] + nums[i] ? dp[j] : dp[j-nums[i]] + nums[i];}}//如果dp[target] == target//说明可以将这个数组分割成两个子集,使得两个子集的元素和相等。if(dp[target] == target) return true;return false;
}

在此也给出二维数组的求解:
 

bool canPartition(int* nums, int numsSize) {int sum = 0;for(int i = 0;i<numsSize;i++){sum += nums[i];}if(sum % 2 == 1){return false;}int traget = sum / 2;int dp[numsSize+1][traget+1];memset(dp,0,sizeof(dp));for(int i = nums[0];i<=traget;i++){dp[0][i]=nums[0];}for(int i = 1;i<numsSize;i++){for(int j = 0;j<=traget;j++){if(j<nums[i]){dp[i][j] = dp[i-1][j];}else{dp[i][j] = dp[i-1][j] > (dp[i-1][j-nums[i]]+nums[i]) ? dp[i-1][j]: (dp[i-1][j-nums[i]]+nums[i]);}}}if(dp[numsSize-1][traget] == traget){return true;}else{return false;}
}


http://www.ppmy.cn/news/1571875.html

相关文章

如何在 Java 应用中实现数据库的主从复制(读写分离)?请简要描述架构和关键代码实现?

在Java应用中实现数据库主从复制&#xff08;读写分离&#xff09; 一、架构描述 &#xff08;一&#xff09;整体架构 主库&#xff08;Master&#xff09; 负责处理所有的写操作&#xff08;INSERT、UPDATE、DELETE等&#xff09;。它是数据的源头&#xff0c;所有的数据变…

Visual Studio 进行单元测试【入门】

摘要&#xff1a;在软件开发中&#xff0c;单元测试是一种重要的实践&#xff0c;通过验证代码的正确性&#xff0c;帮助开发者提高代码质量。本文将介绍如何在VisualStudio中进行单元测试&#xff0c;包括创建测试项目、编写测试代码、运行测试以及查看结果。 1. 什么是单元测…

Maven 多模块项目管理

1. 什么是 Maven 多模块项目&#xff1f; 在 Maven 中&#xff0c;多模块项目是指一个父项目管理多个子模块的项目结构。每个子模块都可以是一个独立的模块或应用&#xff0c;但都在同一个父 POM 文件的管理下。通过这种结构&#xff0c;团队可以更好地组织大型项目&#xff0…

机器学习数学公式推导笔记

正定方程是凸函数证明 范数 向量的范数与内积 范数例子

1.攻防世界 unserialize3(wakeup()魔术方法、反序列化工作原理)

进入题目页面如下 直接开审 <?php // 定义一个名为 xctf 的类 class xctf {// 声明一个公共属性 $flag&#xff0c;初始值为字符串 111public $flag 111;// 定义一个魔术方法 __wakeup()// 当对象被反序列化时&#xff0c;__wakeup() 方法会自动调用public function __wa…

rabbitMQ数据隔离

用户管理 点击Admin选项卡&#xff0c;就会呈现rabbitMQ控制台的用户管理界面 Name&#xff1a;sde&#xff0c;也就是用户名Tags&#xff1a;administrator&#xff0c;说明sde用户是超级管理员&#xff0c;拥有所有权限Can access virtual host&#xff1a; /&#xff0c;可…

2526考研资料分享 百度网盘

通过网盘分享的文件&#xff1a;01、2026【考研数学】 链接:https://pan.baidu.com/s/1PwMzp_yCYqjBqa7492mP3w?pwd98wg 提取码:98wg--来自百度网盘超级会员v3的分享 通过网盘分享的文件&#xff1a;01、2026【考研政治】 链接:https://pan.baidu.com/s/1PwMzp_yCYqjBqa7492…

全链路数据引擎:WhaleStudio驱动下的大数据调度与同步智能革新

在数字化转型不断加速的今天&#xff0c;数据已成为企业最宝贵的资产&#xff0c;而如何高效地处理、传输和协调这些海量数据成为企业制胜的关键。大数据调度与同步正是支撑这一核心业务的两大技术支柱。本文将详细阐述大数据调度与同步的工作原理、二者之间的紧密关系以及它们…