LeetCode刷题---打家劫舍问题

顾得泉:个人主页

个人专栏:《Linux操作系统》  《C/C++》  《LeedCode刷题》

键盘敲烂,年薪百万!


一、打家劫舍

题目链接:打家劫舍

题目描述

       你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

       给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。偷窃到的最高金额 = 2 + 9 + 1 = 12 。

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 400

解法

1.状态表示:

       对于简单的线性dp,我们可以用「经验+题目要求」来定义状态表示:

            i.以某个位置为结尾,巴拉巴拉;

            ii.以某个位置为起点,巴拉巴拉。

       这里我们选择比较常用的方式,以某个位置为结尾,结合题目要求,定义一个状态表示:

            dp[i]表示:选择到i位置时,此时的最高金额。

       但是我们这个题在1位置的时候,会面临「选择」或者「不选择」两种抉择,所依赖的状态需要细分:

       f[i]表示:选择到i位置时,nums[i]必选,此时的最高金额;

       g[i]表示:选择到i位置时,nums[i]不选,此时的最高金额。

2.状态转移方程:

       因为状态表示定义了两个,因此我们的状态转移方程也要分析两个:

对于f[i]:

       如果nums[i]必选,那么我们仅需知道[i - 1]位置在不选的情况下的最高金额,然后加上nums[i]即可,因此f[i] = g[i - 1]+ nums[i]

对于g[i]:

       如果nums[j]不选,那么[i - 1]位置上选或者不选都可以。因此,我们需要知道[i- 1]位宣上选或者不选两种情况下的最长时长,因此 g[i] = max (f[i - 1],g[i- 1])

3.初始化:

       这道题的初始化比较简单,因此无需加辅助节点,仅需初始化 f[0] = nums[0],g[0] = 0即可

4.填表顺序:

       根据「状态转移方程」得「从左往右,两个表一起填」

5.返回值

       根据「状态表示」,应该返回max(f[n - 1],g[n - 1])

代码实现

class Solution {
public:int rob(vector<int>& nums) {int n = nums.size();if(n == 0) return nums[0];vector<int> f(n);auto g = f;f[0] = nums[0];for(int 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]);}
};

二、打家劫舍Ⅱ

题目链接:打家劫舍 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 。

示例 3:

输入:nums = [1,2,3]
输出:3

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 1000

解法

       这一个问题是「打家劫舍」问题的变形。

       上一个问题是一个「单排」的模式,这一个问题是一个「环形」的模式,也就是首尾是相连的。但是我们可以将「环形」问题转化为「两个单排」问题:

       a.偷第一个房屋时的最大金额×,此时不能偷最后一个房子,因此就是偷[0,n - 2]区间的房子;

       b.不偷第一个房屋时的最大金额y,此时可以偷最后一个房子,因此就是偷[1,n - 1]区间的房子;

       两种情况下的「最大值」,就是最终的结果

       因此,问题就转化成求「两次单排结果的最大值」

代码实现

class Solution {
public:int rob(vector<int>& nums) {int n = nums.size();return max(nums[0] + rob1(nums, 2, n - 2), rob1(nums, 1, n - 1));}int rob1(vector<int>& nums, int left, int right){if(left > right)  return 0;int n = nums.size();vector<int> f(n);auto g = f;f[left] = nums[left];for(int i = left + 1; 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]);}
};

三、删除并获得点数

题目链接:删除并获得点数

题目描述

       给你一个整数数组 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 个点数。

提示:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 104

解法

       其实这道题依旧是「打家劫舍」问题的变型。我们注意到题目描述,选择×数字的时候,×-1与x+1是不能被选择的。像不像「打家劫舍」问题中,选择i位置的金额之后,就不能选择i - 1位置以及i+1位置的金额呢~

       因此,我们可以创建一个大小为10001(根据题目的数据范围)的hash 数组,将nums 数组中每一个元素×,累加到,hash 数组下标为x的位置处,然后在hash数组上来一次「打家劫舍」即可

代码实现

class Solution {
public:int deleteAndEarn(vector<int>& nums) {const int n = 10001;int arr[n] = {0};for(auto x : nums) arr[x] += x;vector<int> f(n);auto g = f;for(int i = 1; i < n; i++){f[i] = g[i-1] + arr[i];g[i] = max(f[i-1], g[i-1]);}return max(f[n-1], g[n-1]);}
};

结语:今日的刷题分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~ 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CTO对生活和工作一点感悟

陌生人&#xff0c;你好啊。 感谢CSDN平台让我们有了隔空认识&#xff0c;交流的机会。 我是谁&#xff1f; 我呢&#xff0c;毕业快11年&#xff0c;在网易做了几年云计算&#xff0c;后来追风赶上了大数据的浪潮&#xff0c;再到后来混迹在AI、智能推荐等领域。 因为有一颗…

Discuz论坛自动采集发布软件

随着网络时代的不断发展&#xff0c;Discuz论坛作为一个具有广泛用户基础的开源论坛系统&#xff0c;其采集全网文章的技术也日益受到关注。在这篇文章中&#xff0c;我们将专心分享通过输入关键词实现Discuz论坛的全网文章采集&#xff0c;同时探讨采集过程中伪原创的发布方法…

菜鸟学习日记(Python)——基本数据类型

Python 中的变量不需要声明。每个变量在使用前都必须赋值&#xff0c;变量赋值以后该变量才会被创建。 在 Python 中&#xff0c;变量就是变量&#xff0c;它没有类型&#xff0c;我们所说的"类型"是变量所指的内存中对象的类型。 等号&#xff08;&#xff09;用来…

计算机网络:应用层(下篇)

文章目录 前言一 、电子邮件&#xff08;Email&#xff09;1.邮件服务器2.SMTP[RFC 2821]3.邮件报文格式4.邮件访问协议 二、DNS&#xff08;域名系统&#xff09;1.DNS的历史2.DNS总体思路和目标&#xff08;1&#xff09;问题1&#xff1a;DNS名字空间&#xff08;2&#xff…

nodejs+vue+elementui+express青少年编程课程在线考试系统

针对传统线下考试存在的老师阅卷工作量较大&#xff0c;统计成绩数据时间长等问题&#xff0c;实现一套高效、灵活、功能强大的管理系统是非常必要的。该系统可以迅速完成随机组卷&#xff0c;及时阅卷、统计考试成绩排名的效果。该考试系统要求&#xff1a;该系统将采用B/S结构…

Java全栈基础篇--集合

集合 集合&#xff1a;集合是java中提供的一种容器&#xff0c;可以用来存储多个数据。 特点&#xff1a; 长度不固定&#xff0c;还可以存储不同的数据&#xff08;但是一般都用同一类型&#xff09; 集合和数组既然都是容器&#xff0c;它们有啥区别呢&#xff1f; 数组的长…

在Spring Boot中使用JavaMailSender发送邮件

用了这么久的Spring Boot&#xff0c;我们对Spring Boot的了解应该也逐步进入正轨了&#xff0c;这篇文章讲的案例也在我们的实际开发中算是比较实用的了&#xff0c;毕竟我们完成注册功能和对用户群发消息&#xff0c;都可以采用到邮箱发送功能&#xff0c;往下看&#xff0c;…

Linux基础操作三:Linux操作命令-目录文件操作

1、关机和重启 关机shutdown -h now 立刻关机shutdown -h 5 5分钟后关机poweroff 立刻关机 重启shutdown -r now 立刻重启shutdown -r 5 5分钟后重启reboot 立刻重启 2、帮助 --help命令shutdown --help&#xff1a;…

【论文阅读】1 SkyChain:一个深度强化学习的动态区块链分片系统

SkyChain 一、文献简介二、引言及重要信息2.1 研究背景2.2 研究目的和意义2.3 文献的创新点 三、研究内容3.1模型3.2自适应分类账协议3.2.1状态块创建3.2.2合并过程3.2.3拆分过程 3.3评价框架3.3.1性能3.3.1.1共识延迟3.3.1.2重新分片延迟3.3.1.3处理事务数3.3.1.4 约束 3.3.2 …

docker-compose脚本编写及常用命令

安装 linux DOCKER_CONFIG/usr/local/lib/docker/cli-plugins sudo mkdir -p $DOCKER_CONFIG/cli-plugins sudo curl -SL https://521github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose sudo c…

VBA代码解决方案第8讲:用FindPrevious进行重复搜索及利用LIKE查找

《VBA代码解决方案》(版权10028096)这套教程是我最早推出的教程&#xff0c;目前已经是第三版修订了。这套教程定位于入门后的提高&#xff0c;在学习这套教程过程中&#xff0c;侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码…

【电源专题】DC/DC电源FB分压电阻设计注意事项

在DC/DC电源中我们不可避免的会遇到FB分压电阻的取值,PCB设计等问题。如下所示随意打开一份同步降压稳压器规格书TPS56320X,规格书中的简化电路原理图就已经存在VFB管脚上的两个分压电阻。 很多工程师朋友们会误认为分压电阻只是简单的将输出电压缩小到参考电压,通过此电压来…