【LeetCode】动态规划 刷题训练(四)

news2024/12/23 14:01:11

文章目录

  • 面试题 17.16. 按摩师(打家劫舍|)
    • 题目解析
    • 状态转移方程
    • 完整代码
  • 213. 打家劫舍 II
    • 题目解析
    • 状态转移方程
    • 完整代码
  • 740. 删除并获得点数
    • 题目解析
    • 预处理
    • 状态转移方程
    • 完整代码

面试题 17.16. 按摩师(打家劫舍|)

点击查看:按摩师


一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。

示例 1:
输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。
示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。


题目解析

从第一个数1开始,相邻的数不能够放在一起,所以再次 选择 3
即 1+3 =4
从第二个数2开始,相邻的数不能够放在一起,所以再次 选择 1
即 2+1 =3
所以 4 作为最长预约时长

状态转移方程

在上述分析过程中发现,是从左往右的

dp[i] :表示 选到i位置的时候,此时的最长预约时长


对于i位置有两种情况:

1. 选择i 位置的值,选择用f 表示
f[i]:表示 选择i位置的时候,i位置的值(nums[i]) 必选,此时的最长预约时长

2. 不选 i位置的值,不选用g表示
g[i]:表示 选择i位置的时候,i位置的值(nums[i]) 不选, 此时的最长预约时长


f[i]表示 i位置必定选择,则i-1位置必定不能被选
因为要的是最长预约时长,所以寻找[0,i-1] 区间内的最长预约时长 ,而i-1位置不能够被取到 即g[i-1]
再加上i位置的值 为 [0,i]区间的最长预约时长

状态转移方程 为:
f[i] = g[i-1]+nums[i]


g[i] 表示 i位置必定不选,则i-1位置分为两种情况
第一种情况,i-1位置被选择
因为要的是最长预约时长,所以寻找[0,i-1] 区间内的最长预约时长 ,而i-1位置能够被取到 即f[i-1]
第一种情况下的最长预约时长为 : g[i]=f[i-1]

第二种情况,i-1位置不选
因为要的是最长预约时长,所以寻找[0,i-1] 区间内的最长预约时长 ,而i-1位置不能够被取到 即g[i-1]
第二种情况下的最长预约时长为 : g[i]=g[i-1]

状态转移方程为:
g[i] =max(f[i-1],g[i-1]);


完整代码

class Solution {
public:
    int massage(vector<int>& nums) {
       int n=nums.size();

       //处理边界条件
       if(n==0)
       {
           return 0;
       }
       vector<int>f(n,0);
       vector<int>g(n,0);
       int i=0;

       //为了防止越界问题 g[0]和f[0]都需要提前赋值
       g[0]=0;
       f[0]=nums[0];
       for(i=1;i<n;i++)
       {
          f[i]=g[i-1]+nums[i];
          g[i]=max(f[i-1],g[i-1]);
       }
       //返回 取到最后一个位置和 不取最后一个位置 两者的最大值
       return max(f[n-1],g[n-1]);
    }
};

i从1开始,所以要初始化f[0]和g[0]
f[0]包含nums[0]位置的值,所以为nums第一个元素
g[0]不包含nums[0]位置的值,所以为0

返回值为 到最后一个位置选 和到最后一个位置不选,两者中的最大值

213. 打家劫舍 II

点击查看:打家劫舍 II


你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金

示例 1:
输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
示例 2:
输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。

题目解析

相当于 打家劫舍| 不同点在于 首尾是相连的

若取第一个节点中的值 2 ,则不能取第三个节点中的值 2 ,因为收尾相连 ,所以此时 能够偷取的金额为2

若 取 第二个节点中的值 3 ,则能够偷取的金额为3
所以 最大偷取金额 为 3

通过分类讨论,将环形问题,转换为两个线性的打家劫舍|


情况一:

若偷取下标为0 的位置,因为首尾相连,所以下标为1的 位置 和 下标为n-1的位置就不能偷取到了
而在[2,n-2]区间内 随便偷取(用动态转移方程)


情况二:

若 不偷取 下标为0的位置,此时[1,n-1]区间内可以随便偷取(用动态转移方程)

取 两种情况下的最大值 即为 最大金额

状态转移方程

该动态转移方程 是用于上述分析的情况1中[2,n-2]区间内 随便偷取 和情况2中[1,n-1]区间内可以随便偷取的 情况


f[i]:表示偷取到i位置时,偷nums[i],此时的最大金额
g[i]:表示偷取到i位置时,不偷nums[i],此时的最大金额


若i位置被偷取到 nums[i]的值,则想要求[0,i]的最大金额,就要先求[0,i-1]的最大金额
而由于相邻位置不能偷取,所以i-1位置不能偷取,即g[i-1]
再加上nums[i]的值 为为 [0,i]区间的最大金额

状态转移方程 为:
f[i]=g[i-1]+nums[i]


若i位置没有被偷取到 nums[i]的值,则i-1位置分为两种情况:

情况一:
若i-1位置的值被偷取,
因为要的是最大金额,所以寻找[0,i-1] 区间内的最长金额 ,而i-1位置能够被取到 即f[i-1]
第一种情况下的最大金额为 : g[i]=f[i-1]

情况二:
若i-1位置的值没有被偷取,
因为要的是最大金额,所以寻找[0,i-1] 区间内的最大金额 ,而i-1位置不能够被取到 即g[i-1]
第二种情况下的最长最大金额为 : g[i]=g[i-1]

状态转移方程 为:
g[i]=max(f[i-1],g[i-1]);

完整代码

class Solution {
public:
    int rob1(vector<int> &nums,int left,int right)
    {
        //区间不存在
        if(left>right)
        {
            return 0;
        }
        int n=nums.size();
        vector<int>f(n,0);
        vector<int>g(n,0);
        int i=0;
        //为了防止越界问题,所以下标left处要提前赋值
        f[left]=nums[left];
        g[left]=0;
        for(i=left;i<=right;i++)
        {
            f[i]=g[i-1]+nums[i];
            g[i]=max(f[i-1],g[i-1]);
        }
        //求 取到最后一个位置 和 没有取到最后一个位置 两者的最大值
        return max(f[right],g[right]);
    }
    int rob(vector<int>& nums) {
        int n=nums.size();
        //第一个位置取到值 和 第一个位置没有取到值 的两种情况
       return max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1));
    }
};

n的取值为1到100,若n为1时,n-2为-1,就会导致下标left(1) 小于下标right(2) ,区间不存在

调用rob1,就在区间[left,right]内随便偷取,就相当于打家劫舍|的代码在调用

740. 删除并获得点数

点击查看:删除并获得点数


给你一个整数数组 nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例 1:
输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。
示例 2:
输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。

题目解析

在这里插入图片描述
删除一个3,并获取3个点数,同时所有的2和4也被删除,依次删除3,并获取对应的点数
共获取 9个点数

预处理

若储存的数都是连续的,则相当于打家劫舍问题(不能选择两个相邻的数)
如:若选取 1 ,则不能选取2


但是像这种不连续的数 ,缺少数字3和5 6,就没办法使用 类似打家劫舍问题的解决方法


借助下标表示 对应的数,如:下标为1,表示为1的数
arr[i] :表示 i 这个数,出现的总和
此时的下标就是连续的,就可以借助 打家劫舍问题的解决方法
如:若选取下标为1的数,则就不能选取下标为2的数,只能选择下标为3的数或者 下标为4的数

将原数组中数统计到 arr数组中,在arr数组中进行 打家劫舍

状态转移方程

以下就是 打家劫舍问题的状态转移方程(就是把原数组变为了arr数组,其他都是一样的)


对于i位置有两种情况:
1. 选择i 位置的值,选择用f 表示
f[i]:表示 选择i位置的时候,i位置的值(arr[i]) 必选,此时的最大点数

2. 不选 i位置的值,不选用g表示
g[i]:表示 选择i位置的时候,i位置的值(arr[i]) 不选, 此时的最大点数


f[i]表示 i位置必定选择,则i-1位置必定不能被选
因为要的是最大点数,所以寻找[0,i-1] 区间内的最大点数 ,而i-1位置不能够被取到 即g[i-1]
再加上i位置的值 为 [0,i]区间的最大点数

状态转移方程 为:
f[i] = g[i-1]+arr[i]


g[i] 表示 i位置必定不选,则i-1位置分为两种情况
第一种情况,i-1位置被选择
因为要的是最大点数,所以寻找[0,i-1] 区间内的最大点数 ,而i-1位置能够被取到 即f[i-1]
第一种情况下的最大点数为 : g[i]=f[i-1]

第二种情况,i-1位置不选
因为要的是最大点数,所以寻找[0,i-1] 区间内的最大点数 ,而i-1位置不能够被取到 即g[i-1]
第二种情况下的最大点数为 : g[i]=g[i-1]

状态转移方程为:
g[i] =max(f[i-1],g[i-1]);

完整代码

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
         int i=0;
         int maxsize=0;
         //因为arr数组下标最大值为原数组的最大值 所以寻找原数组的最大值
         for(i=0;i<nums.size();i++)
         {
            if(nums[i]>maxsize)
            {
                maxsize=nums[i];
            }
         }
         //通过原数组的最大值创建arr数组大小
         vector<int>arr(maxsize+1,0);
         for(i=0;i<nums.size();i++)
         {
             //arr[i]代表 i这个数的总和
             arr[nums[i]]+=nums[i];
         }
         //下面进行 打家劫舍问题
        int n=arr.size();
        //[i]f代表取arr[i]这个位置的时候,能够得到的最大点数
        //g[i]代表不能取arr[i]这个位置的时候,能够得到的最大点数
         vector<int>g(n,0);
         vector<int>f(n,0);
         //为了避免越界 将g[0] f[0]进行初始化
         g[0]=0;
         f[0]=arr[0];
         for(i=1;i<n;i++)
         {
             //状态转移方程
             f[i]=g[i-1]+arr[i];
             g[i]=max(g[i-1],f[i-1]);
         }
         //返回 取到最后一个位置 和 不取最后一个位置 两者中的最大值
         return max(f[n-1],g[n-1]);
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【vue小知识】给DOM元素动态的添加上一个类||v-bind的妙用

&#x1f609;博主&#xff1a;初映CY的前说(前端领域) ,&#x1f4d2;本文核心&#xff1a;vue文件怎么给DOM元素加上一个类 项目场景&#xff1a; 在前端页面逻辑操作中通常是存在click事件,添加点击效果是为了让页面操作起来更加的有操作性与互动性,那么有什么方式可以实现…

13个有趣的Python高级脚本!

关注“Python专栏”微信公众号&#xff0c;回复暗号【面试大全】&#xff0c;立即领取面试题简历模板。 每天我们都会面临许多需要高级编码的编程挑战。你不能用简单的 Python 基本语法来解决这些问题。在本文中&#xff0c;我将分享 13 个高级 Python 脚本&#xff0c;它们可以…

IP路由选择过程

1.1路由选择基础 路由选择是指将分组从一个设备通过互联网络发往位于不同网络上的另一个设备的操作。路由器不关注网络中的主机&#xff0c;而只关注互联起来的网络以及通往各个网络的最佳路径。 目标主机的逻辑网络地址用来获取通过可路由网络传送到指定网络中的分组&#xf…

(一)CSharp-Socket

一、套接字 Windows Sockets 只支持一个通信域&#xff1a;网际域&#xff08;AF-INET&#xff09;&#xff0c;这个域被使用网际协议族通信的进程所使用。 TCP/IP 的 Socket 则提供3种类型的套接字 1、流式套接字&#xff08;SOCK_STREAM&#xff09; 提供面向连接、可靠的数…

STM32 Proteus仿真闹钟设定万年历系统DS1302北京时间LCD1602蜂鸣器报警-0045

STM32 Proteus仿真闹钟设定万年历系统DS1302北京时间LCD1602蜂鸣器报警-0045 Proteus仿真小实验&#xff1a; STM32 Proteus仿真闹钟设定万年历系统DS1302北京时间LCD1602蜂鸣器报警-0045 功能&#xff1a; Protues版本&#xff1a;8.9 硬件组成&#xff1a;STM32F103R6单…

gif格式怎么转换成mp4? 这两个方法实用方便!

GIF&#xff08;Graphics Interchange Format&#xff09;文件是一种常见的动态图像格式&#xff0c;而MP4&#xff08;MPEG-4 Part 14&#xff09;则是一种流行的视频文件格式。有时候&#xff0c;您可能想要将GIF文件转换为MP4格式&#xff0c;以便在不同的平台和设备上进行更…

6-js基础-5

JavaScript 基础 - 5 知道对象数据类型的特征&#xff0c;能够利用数组对象渲染页面 对象综合案例数据类型存储 对象 对象&#xff08;Object&#xff09;&#xff1a;JavaScript里的一种数据类型&#xff08;引用类型&#xff09;&#xff0c;也是用于存储数据的 好处&#x…

机器学习笔记 - 了解机器学习中的小样本(Few-Shot)学习

一、背景概述 深度学习模型在图像分类、语义分割、对象检测等计算机视觉任务中的成功归功于利用了用于训练网络的大量标记数据——一种称为监督学习的方法。尽管在这个信息技术时代有大量的非结构化数据可用,但注释数据很难获得。 由于这个原因,计算机视觉机器学习项目中数据…

python spider 爬虫 之 urllib系列 urlretrieve下载照片、视频 网页

python 中 集成了 urllib urllib import urllib.request # urlopen 方法 url"url" response urllib.request.urlopen(url)print(type(response )) print(response.read()) # 解码 字节--->字符串 decode 字符串--》字节 encode print(response.read()…

腾讯课堂Python课程哪家强?

腾讯课堂Python课程哪家强&#xff1f; 文章目录 腾讯课堂Python课程哪家强&#xff1f;一、前言二、数据读取和数据预处理1、数据读取2、数据处理 三、有多少人愿意花钱学Python&#xff1f;四、多少价位的课买的人最多&#xff1f;五、哪家机构的课最多&#xff1f;销量最好&…

来评选你心中的TOP1编程语言

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

WEBGIS系统数据库设计

文章目录 系统设备模型设计1 .设备模型结构2. 设备逻辑关系模型系统属性数据库设计1 . 系统属性数据库2 . 实体继承关系1) 电气实体部分2 &#xff09;土建实体部分3 &#xff09;其他实体联系 系统采用PostgreS QL 作为属性数据库&#xff0c; PostGIS 作为空间数据库&#xf…

CENTOS上的网络安全工具(二十六)SPARK+NetSA Security Tools容器化部署(2)

〇、抓包与批量转换cap文件 1. Network Monitor 抓包 我们在CENTO OS上的网络安全工具&#xff08;十七&#xff09;搭建Cascade的Docker开发环境中捎带脚介绍了以下windows下的抓包软件。大意就是微软又一款不错的抓包分析软件&#xff0c;名曰nmcap&#xff0c;可在Download …

MySQL——备份与恢复

文章目录 MySQL 完全备份物理冷备份与恢复mysqldump 备份与恢复 MySQL 完全恢复MySQL 增量备份与恢复MySQL 增量备份MySQL 增量恢复 MySQL 完全备份 InnoDB存储引擎的数据库在磁盘上存储成三个文件&#xff1a;db.opt(表属性文件)、表名.frm(表结构文件)、表名.ibd(表数据文件…

FPGA解码 4K MIPI 视频 纯vhdl实现 CSI2 RX 采集OV13850,提供工程源码和技术支持

目录 1、前言2、Xilinx官方主推的MIPI解码方案3、本方案的性能及其优越性4、我这里已有的 MIPI 编解码方案5、vivado工程介绍6、上板调试验证7、福利&#xff1a;工程代码的获取 1、前言 FPGA图像采集领域目前协议最复杂、技术难度最高的应该就是MIPI协议了&#xff0c;MIPI解…

本地部署开源大模型的完整教程:LangChain + Streamlit+ Llama

在过去的几个月里&#xff0c;大型语言模型(llm)获得了极大的关注&#xff0c;这些模型创造了令人兴奋的前景&#xff0c;特别是对于从事聊天机器人、个人助理和内容创作的开发人员。 大型语言模型(llm)是指能够生成与人类语言非常相似的文本并以自然方式理解提示的机器学习模型…

【FreeRTOS】Arduino开发STM32

0.开发环境(工具) Vscode 、platformio、arduino、STM32F103C8T6、USB-TTL 引脚连接&#xff1a;STM32直接设置为烧录模式即可&#xff0c;烧录完成后会自动运行程序。 1.点灯加串口输出调试 注意事项&#xff1a;每次上传程序前&#xff0c;需要按一下复位键。 #include &…

【Linux】2、文件系统、Rootfs

文章目录 一、文件系统二、Rootfs2.1 各目录约定2.1.1 /bin4.2 /boot4.3 /dev4.4 /etc4.5 /home4.6 /lib4.7 /media4.8 /mnt4.9 /opt4.10 /root4.11 /run4.12 /sbin4.13 /srv4.14 /tmp4.15 /usr4.16 /var 一、文件系统 Linux 的文件系统遵循 HFS 设计&#xff0c;有如下实现&a…

浅谈充电桩监控系统的必要性

关注acrelzxz&#xff0c;了解更多详情 摘要&#xff1a;针对当前电动汽车续航能力严重不足以及不能及时充电的问题&#xff0c;将电力电子变流技术、智能监控技术、REIP无线射频技术及CAN总线技术应用到电动汽车智能充电桩的设计与研究中。开展了无人值守的智能电动车充电桩的…

Android 使用webView打开网页可以实现自动播放音频

使用webview 自动播放音视频&#xff0c;场景如&#xff0c;流媒体自动部分&#xff0c;音视频通话等。会出现如下问题&#xff1a; 解决方案如下&#xff1a; 配置webview 如下&#xff0c;这样可以自动播放音频。 webView.getSettings().setMediaPlaybackRequiresUserGestur…