【代码随想录算法训练营Day40】01背包问题一维dp数组;二维dp数组(滚动数组);416.分割等和子集

文章目录

  • ❇️Day 41 第九章 动态规划 part04
    • ✴️今日任务
    • ❇️01背包问题 二维
      • 背包问题的区别
      • 暴力解法
      • 动规五部曲
    • ❇️01背包问题 一维
      • 二维转一维:滚动数组
      • 动规五部曲
    • ❇️416. 分割等和子集
      • 随想录思路
      • 自己的思路
        • 二维方法
        • 一维方法
      • 自己的代码
        • 二维方法
        • 一维方法

❇️Day 41 第九章 动态规划 part04

✴️今日任务

正式开始背包问题,背包问题还是挺难的,虽然大家可能看了很多背包问题模板代码,感觉挺简单,但基本理解的都不够深入。
如果是直接从来没听过背包问题,可以先看文字讲解慢慢了解 这是干什么的。
如果做过背包类问题,可以先看视频,很多内容,是自己平时没有考虑到位的。 背包问题,力扣上没有原题,大家先了解理论,今天就安排一道具体题目。

  • 01背包问题,你该了解这些!
  • 01背包问题,你该了解这些! 滚动数组
  • 416.分割等和子集

❇️01背包问题 二维

  • 视频讲解:https://www.bilibili.com/video/BV1cg411g7Y6
  • 文章链接:https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-1.html

背包问题的区别

  1. 0-1背包:n种物品,每种物品只有一个
  2. 完全背包:n种物品,每种物品有无限个
  3. 多重背包:n种物品,每种物品的个数各不相同

暴力解法

利用回溯列举出每一种方法

动规五部曲

  1. dp数组的含义:dp[i][j]:[0,i]之间的物品任取,在容量为j时最大价值为dp[i][j]
  2. 递归公式:dp[i][j] = Math.max(dp[i - 1][j - weight[i]] + value[i], dp[i - 1][j]);
    • 不放物品i:dp[i - 1][j](也就是前面i-1个物品放不放的最大价值)
    • 放物品i:dp[i - 1][j - weight[i]] + value[i]
  3. 初始化
    1. 由递归公式得出dp[i][j]是由dp[i - 1][j]和dp[i - 1][j]推出来的(上方和左上角)
    2. 所以需要初始化第一列和第一行,且具体情况具体分析
    3. 第一列dp[i][j = 0],容量为0价值自然为0;
    4. 第一行dp[i = 0][j],只能放物品0,01背包只能放一个,所以用value[0]初始化第一行,但要注意物品0的重量,j < weight[0]时dp[0][j] = 0
    5. 其他地方不需要初始化,之后会被赋值更新
  4. 遍历顺序
    1. 对于二维的01背包问题,两个for循环先遍历背包or先遍历物品都可以
    2. 先遍历物品:从左到右从上到下一行一行遍历
    3. 先遍历背包:从上到下从左到右一列一列遍历
    4. 因为dp[i][j]取决于上方和左上方的数,所以这两种遍历方式都可以
      [图片]

❇️01背包问题 一维

  • 视频讲解:https://www.bilibili.com/video/BV1BU4y177kY
  • 文章链接:https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-2.html

二维转一维:滚动数组

为什么二维可以转变为一维:

  • 根据二维的递归公式:dp[i][j] = Math.max(dp[i - 1][j] - weight[i] + value[i], dp[i - 1][j]);
  • dp[i][j]是通过上一层dp[i - 1][]的数据得到的
  • 想法是:将dp[i - 1][]的数据拷贝到下一层dp[i][]这样dp[i][j]就可以在自己层操作
  • 相当于把矩阵压缩成了一行,数据是一个滚动的状态,所以也叫滚动数组

动规五部曲

  1. dp数组的含义:dp[j]:容量为j的背包可以放的最大价值为dp[j]
  2. 递归公式:dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
    1. 不放物品i:dp[j],原来是dp[i - 1][j]但上一层数据已经拷贝下来了所以是dp[j]
    2. 放物品i:dp[j - weight[i]] + value[i]
  3. 初始化:dp[0] = 0;
  4. 遍历顺序:倒序遍历
    1. 如果正序遍历取用前面的数值已经被覆盖掉了会影响后面数据的取值
    2. 二维数组转化成一维数组的时候,是将上一层的值直接拷贝到当前层,但是从二维数组的计算中,我们可以发现计算当前值是需要利用上方和左边的值,从右向前遍历,我们是从右往左覆盖,这时候左边的值还可以用

❇️416. 分割等和子集

  • 本题是 01背包的应用类题目
  • 题目链接:https://leetcode.cn/problems/partition-equal-subset-sum/
  • 视频讲解:https://www.bilibili.com/video/BV1rt4y1N7jE
  • 文章链接:https://programmercarl.com/0416.%E5%88%86%E5%89%B2%E7%AD%89%E5%92%8C%E5%AD%90%E9%9B%86.html

随想录思路

  1. 分成两个元素和相等的子集,所以每个子集的和都是数组和的一半
  2. 转换成背包问题:看数组中的元素是否能装满容量为一半和的背包
    1. nums[i]即是重量也是价值
    2. 所以判断能否装满的条件dp[nums.length - 1][target] == target
  3. 因为数组中的元素只能用一次,所以是01背包问题

自己的思路

二维方法
  1. dp数组的含义:dp[i][j]:[0,i]物品中任意放入容量为j的背包中的最大价值为dp[i][j]
    1. i最大为nums.length - 1
    2. j最大为nums元素总和的一半
  2. 递归公式:dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]);
  3. 初始化:dp[i][0] = 0; if(nums[0] <= j) dp[0][j] = nums[0]; else dp[0][j] = 0;
  4. 遍历顺序:都行
  5. 打印dp数组
一维方法
  1. dp数组的含义:dp[j]:数组中数据任意放入子集,子集的最大和为dp[j]
    1. j最大为nums元素总和的一半
  2. 递归公式:dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
  3. 初始化:dp[0] = 0; if(nums[0] <= j) dp[j] = nums[0]; else dp[j] = 0;
  4. 遍历顺序:倒序遍历
  5. 打印dp数组

自己的代码

二维方法
class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        //如果和为奇数直接返回false
        if(sum % 2 != 0) return false;
        int dp[][] = new int[nums.length][sum / 2 + 1];
        for (int j = 0; j <= sum / 2; j++) {
            if(nums[0] <= j) dp[0][j] = nums[0];
            else  dp[0][j] = 0;
        }
        for (int i = 0; i < nums.length; i++) {
            dp[i][0] = 0;
            //System.out.println(Arrays.toString(dp[i]));
        }
        for (int i = 1; i < nums.length; i++) {
            for (int j = 1; j <= sum / 2; j++) {
                if(j >= nums[i]) {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]);
                }else{
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        
        if(dp[nums.length - 1][sum / 2] == sum / 2){
            return true;
        }else{
            return false;
        }
    }
}
一维方法

踩坑点:
物品要从第二个开始,也就是i要从1开始

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        //如果和为奇数直接返回false
        if(sum % 2 != 0) return false;
        int dp[] = new int[sum / 2 + 1];
        dp[0] = 0;
        for (int j = 0; j <= sum / 2; j++) {
            if(nums[0] <= j)
                dp[j] = nums[0];
            else
                dp[j] = 0;
        }
        //System.out.println(Arrays.toString(dp));
        for (int i = 1; i < nums.length; i++) {
            for (int j = sum / 2; j >= 0; j--) {
                if(j >= nums[i])
                    dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }
        //System.out.println(Arrays.toString(dp));
        if(dp[sum / 2] == sum / 2)return true;
        else return false;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kibana二次开发环境搭建

1 kibana环境搭建 1.1 搭建后端服务 &#xff08;1&#xff09;java环境安装 ElasticSearch运行需要java jdk支持。所以要先安装JAVA环境。由于ElasticSearch 5.x 往后依赖于JDK 1.8的&#xff0c;所以现在我们下载JDK 1.8或者更高版本。下载JDK1.8,下载完成后安装&#xff…

去电脑维修店修电脑需要注意什么呢?装机之家晓龙

每当电脑出现故障时&#xff0c;你无疑会感到非常沮丧。 如果计算机已过了保修期&#xff0c;您将无法享受制造商的免费保修服务。 这意味着您必须自费找到一家电脑维修店。 去电脑维修店并不容易。 大家一定要知道&#xff0c;电脑维修非常困难&#xff0c;尤其是笔记本电脑维…

qtCreator可以全局包含。VSqt中千万不能全局包含,你的控件头文件会自己变成<>括号,编译就报错

qtCreator可以全局包含。 VSqt中千万不能全局包含&#xff0c;你的控件头文件会自己变成&#xff1c;&#xff1e;括号&#xff0c;编译就报错

重建大师6.2版本的建模效果出现下图中模糊的情况,是什么原因?

可能是因为坐标原点设置的不对&#xff0c;图例中的三角网都出现了精度损失的问题。 坐标原点设置的具体操作&#xff1a;提交产品后&#xff0c;在弹出的界面&#xff0c;可以设定坐标原点。 重建大师是一款专为超大规模实景三维数据生产而设计的集群并行处理软件&#xff0…

第七届强网杯-PWN-【warmup】

文章目录 warmup libc 2.35检查IDA逆向maindeldelete_noteadd_noteshow_noteinput_numberread_16atoi __errno_location()相关解释prctl相关 思路高版本off by null利用技巧产生chunk extend泄露libc基地址泄露heap基地址修改放入tcachebin中的chunk的fd为stdout最后add两个chu…

AI大模型助力创意思维,拓展无限可能性

在当今快速发展的科技时代&#xff0c;人工智能大模型正逐渐成为我们生活中不可或缺的一部分。它们拥有强大的计算能力和学习能力&#xff0c;能够帮助我们解决许多复杂的问题&#xff0c;同时也可以为创意思维的拓展提供无限可能性。 人工智能大模型可以通过对海量数据的分析…

docker部署springboot jar包项目

docker部署springboot jar包项目 前提&#xff0c;服务器环境是docker环境&#xff0c;如果服务器没有安装docker&#xff0c;可以先安装docker环境。 各个环境安装docker&#xff1a; Ubuntu上安装Docker&#xff1a; ubuntu离线安装docker: CentOS7离线安装Docker&#xff1…

华为北向网管NCE开发教程(1)闭坑选接口协议

华为北向网管NCE开发教程&#xff08;1&#xff09;闭坑选接口协议 华为北向网管NCE开发教程&#xff08;2&#xff09;REST接口开发 华为北向网管NCE开发教程&#xff08;3&#xff09;CORBA协议开发 本文一是记录自己开发华为北向网管遇到的坑&#xff0c;二是给需要的人&…

Rocky Linux 的安装

1. 为什么用Rocky 因为CentOS不干了&#xff0c;这是CentOS的现状&#xff1a; CentOS Linux 8 在 2021 年底停止更新&#xff1b; CentOS Linux 7 用户较多&#xff0c;这个版本将在 2024 年 6 月 30 日停止支持&#xff1b; 未来社区不会再有 CentOS Linux 的新版本&…

联立方程模型的可识别性的通俗解释

联立方程模型的可识别性&#xff0c;主要的解法是阶条件算法和秩条件算法&#xff0c;数学公式角度的解释就不讲了&#xff0c;参考下面的前人文献。 【计量经济学】联立方程模型-CSDN博客 说一下公式算法背后的通俗原理。 在计量经济模型中&#xff0c;比如 Y23*Xu中&#x…

[java基础揉碎]super关键字

super关键字: 基本介绍 super代表父类的引用&#xff0c;用于访问父类的属性、方法、构造器 super给编程带来的便利/细节 1.调用父类的构造器的好处(分工明确&#xff0c;父类属性由父类初始化&#xff0c;子类的属性由子类初始化) 2.当子类中有和父类中的成员(属性和方法)重…

Springer旗下SCI,16天见刊!稳定检索13年,质量稳定

毕业推荐 SCIE&#xff1a; • 计算机类&#xff0c;6.5-7.0&#xff0c;JCR1区&#xff0c;中科院2区 • 2个月19天录用&#xff0c;6天见刊&#xff0c;36天检索 SCI&EI&#xff08;CCF-C类&#xff09; • 算法类&#xff0c;2.0-3.0&#xff0c;JCR3区&#xff0c…

数字孪生的大方向趋势及未来

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; 数字孪生的大方向趋势及未来 一、引言 数字孪生&#xff08;Digital Twin&#xff09…

高级语言讲义2016计专(仅高级语言部分)

1.斐波那契序列的第n项可以表示成以下形式&#xff0c;编写一个非递归函数&#xff0c;返回该数列的第n项的数值 #include <stdio.h>int func(int n) {if(n1||n2)return 1;int p1,q1,num;for(int i3; i<n; i) {numpq;qp;pnum;}return num; } 2.在MXN的二维数组A中&am…

Win11 没有网络bug

1.问题描述 没有网络&#xff0c;dns一直是固定的&#xff0c;但是dns已经是自动获取了(MAC地址随机) 2.解决办法 1.首先&#xff0c;删除所有网络的手动dns配置,控制中心那个dns管理没有用,在设置中删除网络,不然问题还会出现 - 2.然后&#xff0c;进入注册表\HKEY_LOCAL_MACH…

数据结构之栈详解(C语言手撕)

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

汉服|高校汉服租赁网站|基于Springboot的高校汉服租赁网站设计与实现(源码+数据库+文档)

高校汉服租赁网站目录 目录 基于Springboot的高校汉服租赁网站设计与实现 一、前言 二、系统设计 三、系统功能设计 1、汉服信息管理 2、汉服租赁管理 3、公告管理 4、公告类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选…

滤波器:工作原理和分类及应用领域?|深圳比创达电子EMC

滤波器在电子领域中扮演着重要的角色&#xff0c;用于处理信号、抑制噪声以及滤除干扰。本文将详细介绍滤波器的工作原理、分类以及在各个应用领域中的具体应用。 一、滤波器的定义和作用 滤波器是一种电子设备&#xff0c;用于选择性地通过或阻塞特定频率范围内的信号。其主…

目标检测5:采用yolov8, RK3568上推理实时视频流

上一个效果图&#xff0c;海康球机对着电脑屏幕拍&#xff0c;清晰度不好。 RK3568接取RTSP视频流&#xff0c;通过解码&#xff0c;推理&#xff0c;编码&#xff0c;最终并把结果推出RTSP视频流。 RK3568 推理 数据集采用coco的80个种类集&#xff0c;通过从yovo8.pt&#x…

【Python】新手入门:什么是变量?如何在Python中声明变量?变量有哪些使用方式?

【Python】新手入门&#xff1a;什么是变量&#xff1f;如何在Python中声明变量&#xff1f;变量有哪些使用方式&#xff1f; &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【…