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

【算法训练 day44 分割等和子集】

目录

  • 一、分割等和子集-LeetCode 416
    • 思路
    • 实现代码
      • 1.二维dp代码
      • 2.一维dp代码
    • 问题
    • 总结



一、分割等和子集-LeetCode 416

Leecode链接: leetcode 416
文章链接: 代码随想录
视频链接: B站

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

示例1:

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

思路

本体可以看作一个背包模型,将数组总和除2,将总和一半定义为背包的容量,数组元素为可选的物品。本题既可以定义一个一维dp数组,也可以定义一个二维dp数组,但二维便于理解与讲解并且一维只是二维的精简版,思想基本一致,所以主要写一下二维的思路。数组形式为dp[i][j],i为可选的物品范围,例如当i为3时,表示可选的物品范围为0到3下标的物品任意物品;j表示当前背包的容量大小。dp数组含义为,在j容量下,物品0到i范围可以获得的最大和。递推公式为dp[i][j] = dp[i-1][j]或dp[i][j] = max(dp[i-1][j] , dp[i-1][j-nums[i]] + nums[i])。前者表示不放的情况,后者表示物品放入后可能的情况。不放的条件就是背包容量不足以放下物品,放物品的条件就是当前背包的容量大于或等于当前物品的重量。

实现代码

1.二维dp代码

//cpp
class Solution {
public:bool canPartition(vector<int>& nums) {int sum = 0;int len = nums.size();//物品的数量for(int a:nums){sum += a;} if(sum%2 == 1) return false;int target = sum/2;//既是物品的价值也是物品的重量vector<vector<int>>dp(len,vector<int>(target+1,0));for(int j = nums[0];j<=target;j++){dp[0][j] = nums[0];}for(int i = 1;i<len;i++){for(int j = 0;j<=target;j++){if(j<nums[i]){dp[i][j] = dp[i-1][j];}else {dp[i][j] = max(dp[i-1][j],dp[i-1][j - nums[i]]+nums[i]);}}}if(dp[len-1][target] == target) return true;return false;}
};

2.一维dp代码

//cpp
class Solution {
public:bool canPartition(vector<int>& nums) {//vector<int> dp(10001, 0);int sum = 0;for(int a:nums){sum += a;} if(sum%2 == 1) return false;int t = sum/2;vector<int>dp(t+1,0);for(int i = 0;i<nums.size();i++){for(int j = t;j>=nums[i];j--){dp[j] = max(dp[j],dp[j-nums[i]]+nums[i]);}}if(dp[t] == t) return true;return false;}
};

问题

代码实现细节不熟练,比如初始化时,怎么将第一行的哪些数初始化为恒定值。

总结

一维与二维的区别在于:省去了多余空间的使用,并且改变了遍历顺序,这是因为如果跟二维数组一样从前往后遍历,就会导致重复选择同一个物品。比如,当i = 1时,dp[1] = 1、dp[2] = 1;当i = 2时,dp[1] = 1、dp[2] = 2,显然是不对的因为一件物品只能选一次。虽然一维省去了空间,但时间复杂很高,leetcode上一维dp的执行用时为300ms左右,空间占用达到了10MB左右;二维dp为100ms左右,同样的二维空间占用达到了98MB左右。


相关文章:

  • Mysql 插入或者更新 踩坑
  • QT系列教程(6) 几种标准对话框
  • ReactNative集成到已有iOS项目
  • 大模型日报2024-05-31
  • C++:vector的模拟实现
  • Maven 中的 classifier 属性用过没?
  • chrome 浏览器历史版本下载
  • 从openstack环境中将服务器镜像导出的简单办法
  • 分享 ASP.NET Core Web Api 中间件获取 Request Body 两个方法
  • html+CSS部分基础运用9
  • 大数据系统架构师的论文如何写
  • 【排序算法】选择排序
  • 浅谈线性化
  • 如何修改开源项目中发现的bug?
  • 使用Spring Boot自定义注解 + AOP实现基于IP的接口限流和黑白名单
  • 「面试题」如何实现一个圣杯布局?
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • dva中组件的懒加载
  • express.js的介绍及使用
  • Javascript Math对象和Date对象常用方法详解
  • Java教程_软件开发基础
  • Java面向对象及其三大特征
  • java中的hashCode
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Making An Indicator With Pure CSS
  • nfs客户端进程变D,延伸linux的lock
  • React的组件模式
  • Sass 快速入门教程
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • ViewService——一种保证客户端与服务端同步的方法
  • 创建一个Struts2项目maven 方式
  • 动态魔术使用DBMS_SQL
  • 构建二叉树进行数值数组的去重及优化
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 小程序button引导用户授权
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • ### RabbitMQ五种工作模式:
  • #{}和${}的区别?
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • ()、[]、{}、(())、[[]]命令替换
  • (rabbitmq的高级特性)消息可靠性
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (第二周)效能测试
  • (二)学习JVM —— 垃圾回收机制
  • (七)Appdesigner-初步入门及常用组件的使用方法说明
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • *p=a是把a的值赋给p,p=a是把a的地址赋给p。
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...