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

【算法练习Day40】打家劫舍打家劫舍 II打家劫舍 III

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 打家劫舍
  • 打家劫舍 II
  • 打家劫舍 III
  • 总结:

这一期到了打家劫舍的专题,说是专题但实际上只有一期,而且只有三道题,我们把这三道题放在一起讲,第一道题简单一些,后两道略有不同方向上的难度。但总体来看第一次做可能有一点难想到思路,其实代码实现还是可以的。

打家劫舍

198. 打家劫舍 - 力扣(LeetCode)

题目要求相邻两间房子不能同时遭到盗窃。根据这一条件能够想清如何写出递推公式,则是解题的关键。

dp数组的含义:dp【i】代表了考虑当前第i个位置,是否被偷盗,所能盗得的最大金钱数,注意这里仅仅是考虑这个位置房子是否被偷盗,但是并不是一定会盗窃该房屋,具体是否盗窃该房屋,由递推公式决定。

递推公式: 对于此时遍历到的位置i有两种状态,偷或者不偷,如果是偷那么一定是当前房子被偷获得的价值nums【i】加上当前位置向前数的第二个位置所能获得的最大价值(同样的这个位置也不一定被偷)也就是dp【i-2】,偷该房子的最大获得钱币变成了nums【i】+dp【i-2】,如果不偷该房子,那么该房子的前一个位置就可以被考虑进来是dp【i-1】,它们两个取最大值

dp【i】=max(dp【i-2】+nums【i】,dp【i-1】)。这就是递推公式

我们要时刻记得当前位置i只是被考虑进来偷或者不偷,在递推公式取最大值之前,不能确定该位置一定偷或者不偷。

dp数组的初始化:dp【0】也就是起始位置,我们可以这样假想,加入房子只有一间,那么一定是偷盗了,才能获得最大金钱,所以dp【0】=nums【0】,我们还得为dp【1】初始化,因为递推公式需要用到i的前两个位置,dp【1】=max(nums【0】,nums【1】)是这两个屋子取最大值偷,因为相邻房子不能同时偷,同样可以想成一共只有两个房子,我们考虑偷第一间还是第二间。其余的位置初始化什么数都可以,因为并不能影响最后的答案。

遍历顺序:从前到后,很自然的遍历顺序,并没有考究。

class Solution {
public:int rob(vector<int>& nums) {if(nums.size()==0)return 0;if(nums.size()==1)return nums[0];vector<int>dp(nums.size(),0);dp[0]=nums[0];dp[1]=max(nums[0],nums[1]);for(int i=2;i<nums.size();i++){dp[i]=max(dp[i-2]+nums[i],dp[i-1]);}return dp[nums.size()-1];}
};

思路捋清了发现还是很简单的,但是第一次可能还是有部分想不明白,我刚做该题的思路是这样的:dp【1】初始化为nums【1】,然后最后比较的是偷第一间房屋和不偷哪个价值更大,这样做实际上是有弊端的例如测试用例为{2,1,1,2}时,这种情况是中间两间房子不偷盗,而两边偷盗获得的多。题目虽然要求相邻房子不能偷,但是这并不意味着我们一定要不停偷取才能获得最大金钱!!这就是曲解了dp数组的含义,dp【i】应是考虑i这个位置,而不是一定偷盗,这样想的才能解决这样的测试用例。

下面也给出错误的代码

class Solution {
public:int rob(vector<int>& nums) {if(nums.size()==0)return 0;if(nums.size()==1)return nums[0];vector<int>dp(nums.size(),0);dp[0]=nums[0];dp[1]=nums[1];for(int i=2;i<nums.size();i++){dp[i]=max(dp[i-2]+nums[i],dp[i-1]);}return max(dp[nums.size()-1],dp[nums.size()-2]);}
};

相信对于上面的详细讲解,大家也对于这类问题的入门题目有了一定的了解,下面看一个进阶版本的。

打家劫舍 II

213. 打家劫舍 II - 力扣(LeetCode)

这道题的题目和上一道的唯一区别,在于房子围成一周,第一间房子与最后一间连接起来,并且也不能同时取。线性问题的数组,我们容易想到解题思路,那么环形的我们该如何思考呢?

将该环形数组分为三种情况,我们可以不看两边的房屋,只考虑中间部分 ,这是一种情况,这样中间部分可以像上一道题的思路一样,很轻松做出来,但是两边房屋该怎么办呢?别急还有另外两种情况,不考虑第一个房屋,和不考虑最后一个房屋。实际上这两种情况都包含了第一种情况,由于我们只是考虑这些房屋是否被偷盗,第二三种方法比第一种方法考虑的范围还要远,所以肯定是包含在内,而又由于第一间房屋和最后一间房屋并不能同时放在一起考虑,因为它们成环相连,所以我们只需取得二三种方法中较大得到金钱的那一个,即为最后的答案。将两个范围带入第一个题的函数中去,取得两个最大金钱值,取较大一个即可,看代码实现。

class Solution {
public:int rob(vector<int>& nums) {if(nums.size()==1)return nums[0];if(nums.size()==0)return 0;int result1=fun(nums,0,nums.size()-2);int result2=fun(nums,1,nums.size()-1);return max(result1,result2);}int fun(vector<int>&nums,int start,int end){if(start==end)return nums[start];//防止数组大小等于2vector<int>dp(nums.size(),0);dp[start]=nums[start];dp[start+1]=max(nums[start],nums[start+1]);for(int i=start+2;i<=end;i++){dp[i]=max(dp[i-2]+nums[i],dp[i-1]);}return dp[end];}
};

代码实现是不是也很简单?但是想到思路可不是很容易,尤其对于没有做过很多环形数据的题人来说。特别说明:为什么函数实现里多了一个if(start==end)的判断,我们可能会想正常数组怎么可能传进来的的开始和结束指向同一个位置呢?这其实并不是我们传入错误,有些时候数据可能较短,比如只有两个数据的情况,这样的话按照我们上面的思路,就会出现start和end值一样的情况,我们就要直接返回一个数,因为如果这样再往下走会出现数组越界的情况。

这最后一道是二叉树和动态规划的交叉使用例题,也是树形dp的入门题目。这道题要求对于二叉树的使用要娴熟,而且还要穿插上动态规划的使用,第一次做同样也是有难度的例题。

打家劫舍 III

337. 打家劫舍 III - 力扣(LeetCode)

要求同样是相邻房屋不能被连续抢劫,所以就是取父节点就不能取两个子节点了!

前面的dp数组含义是一样的,不同的是递推公式需要注意一点。

我们要写递归函数来遍历整颗二叉树,需要两个dp数组分别代表左子树和右子树对于该节点偷或者不偷的两种情况分别对应的钱数。说一个误区,题目虽然是说一个父节点只有一个孩子节点,那为什么我们还需要两个dp呢?是因为我们不确定下一个子房子是左子树还是右子树上,所以我们要两个dp数组,而且也可能是一会像左一会向右,所以两边都需要记录,但是仅仅是需要每一个dp数组只有两个参数,dp【0】dp【1】,因为每次递归是会向下遍历的,上一层由系统栈存储,不需要担心每一个节点的数据会丢失。如果当前节点,我们选择偷那么值就是root-> val+leftdp【0】+rightdp【0】,因为取这个节点子节点都不能取,如果不取该节点就是leftdp【1】+rightdp【1】,它们两个最后取最大值就可以了。

细心的盆友肯定会发现,leftdp和rightdp的状态在我们遍历当前节点时候,不是还不能确定下来吗?所以这也是说明我们的遍历顺序是从下往上的后序遍历,把下面的状态推给上一层,这样就可以实现上一层的数据处理依赖下一层的数据了。

class Solution {
public:int rob(TreeNode* root) {vector<int>result=fun(root);return max(result[0],result[1]);}vector<int>fun(TreeNode* root){if(root==NULL)return vector<int>{0,0};vector<int>left=fun(root->left);vector<int>right=fun(root->right);int val1=max(left[0],left[1])+max(right[0],right[1]);int val2=root->val+left[0]+right[0];return {val1,val2};}
};

后序遍历的方法,可以让我们从下向上传递状态转移,遇到空子树,返回的相当于取和不取都是0。最后到根节点往上返回根节点取和不取的两种金钱数,取最大。注意return返回的val1,和val2的顺序不能颠倒,他们是有确定的含义的,返回上一层时候需要调用下一层的两个状态,写反了一定会出问题。

最后,对于递归向上返回时是如何工作的,大家可以自行实现一下,不要只知道代码大概模板,就通过了,做递归类问题最重要的是要知道递归每一步是如何返回的,这样更有利于深刻理解。

总结:

今天我们完成了打家劫舍、打家劫舍 II、打家劫舍 III 三道题,相关的思想需要多复习回顾。接下来,我们继续进行算法练习。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

相关文章:

【算法练习Day40】打家劫舍打家劫舍 II打家劫舍 III

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 打家劫舍打家劫舍 II打家劫…...

双十一运动健身好物推荐,这几款健身好物一定不要错过!

双十一购物狂欢节又要到了&#xff0c;又要到买买买的时候了&#xff01;相信有很多想健身的小白还在发愁不知道买啥装备&#xff1f;别急&#xff0c;三年健身达人这就给你们分享我的年度健身好物&#xff01; 第一款&#xff1a;南卡Runner Pro4s骨传导耳机 推荐理由&#…...

Angular异步数据流编程

1 目前常见的异步编程的几种方法 首先给出一个异步请求的实例&#xff1a; import {Injectable} from angular/core;Injectable({providedIn: root }) export class RequestServiceService {constructor() {}getData() {setTimeout(() > {let res zhaoshuai-lcreturn res…...

古典舞学习的独舞与群舞,古典舞的成品舞蹈教学大全

一、教程描述 本套教程的古典舞是很全面的&#xff0c;不仅有舞蹈动作分解教学&#xff0c;而且有成品舞的完整教学&#xff0c;同时提供独立的背景音乐文件&#xff0c;可以让你更快地学会古典舞。本套教程&#xff0c;大小30.54G&#xff0c;共有276个文件。 二、教程目录 …...

听GPT 讲Rust源代码--library/std(16)

题图来自 EVALUATION OF RUST USAGE IN SPACE APPLICATIONS BY DEVELOPING BSP AND RTOS TARGETING SAMV71[1] File: rust/library/std/src/sync/mpmc/select.rs 在Rust标准库中&#xff0c;rust/library/std/src/sync/mpmc/select.rs文件的作用是实现一个多生产者多消费者的选…...

计算机编程软件编程基础知识,中文编程工具下载分享

计算机编程软件编程基础知识&#xff0c;中文编程工具下载分享 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的软件&#xff0c;象如图这个实例…...

微信小程序里怎么添加砍价活动

随着网络购物的普及&#xff0c;越来越多的消费者开始享受这种方便快捷的购物方式。而在这个大环境下&#xff0c;各种电商活动层出不穷&#xff0c;吸引了众多消费者的关注。而在这些活动中&#xff0c;砍价活动无疑是最受欢迎的一种。今天&#xff0c;我们就来聊一聊如何在小…...

如何在Python爬虫中使用IP代理以避免反爬虫机制

目录 前言 一、IP代理的使用 1. 什么是IP代理&#xff1f; 2. 如何获取IP代理&#xff1f; 3. 如何使用IP代理&#xff1f; 4. 如何避免IP代理失效&#xff1f; 5. 代理IP的匿名性 二、代码示例 总结 前言 在进行爬虫时&#xff0c;我们很容易会遇到反爬虫机制。网站…...

干货丨Linux终端常见用法总结(收藏)

一、前言 熟悉Linux终端的基础用法和常见技巧可以极大提高运维及开发人员的工作效率&#xff0c;笔者结合自身学习实践&#xff0c;总结以下终端用法供同行交流学习。 二、常见用法 1.快捷键 1.1.Alt. 在光标位置插入上一次执行命令的最后一个参数。 1.2.CtrlR 模糊搜索历…...

【RealTek sdk-3.4.14b】RTL8197FH-VG+RTL8812FR实现实现Host 网络和Guest 网络隔离以及各个连接终端间隔离功能

SDK 说明 ** Gateway/AP firmware v3.4.14b – Aug 26, 2019**  Wireless LAN driver changes as:  Refine WiFi Stability and Performance  Add 8812F MU-MIMO  Add 97G/8812F multiple mac-clone  Add 97G 2T3R antenna diversity  Fix 97G/8812F/8814B MP iss…...

【漏洞复现】Metinfo6.0.0任意文件读取漏洞复现

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现代码审计漏洞点 1.5、深度利用EXP编写 1.6、漏洞挖掘1.7修复建议 1.1、漏洞描述 漏洞名称&#xff1a;MetInfo任意文件…...

3.22每日一题(二重积分求平面区域面积)

先复习求平面积分的公式 注&#xff1a;面对平面积分直接使用二重积分对1求积分即可&#xff1b;所以只需要背二重积分的两个公式&#xff1a; 1、直角坐标下对1积分 2、极坐标下对1积分 xy-1是等轴双曲线&#xff01;&#xff01; 1、先画图定区域 2、选择先对x积分还是先对…...

Hadoop环境搭建

1 Hadoop集群环境搭建概述 所谓集群&#xff0c;就是一组通过网络互联的计算机&#xff0c;集群中的每一台计算机称作一个节点&#xff0c;Hadoop集群搭建就是在这个物理集群之上安装部署Hadoop相关的软件&#xff0c;然后对外提供大数据存储和分析等相关服务。 一个前提&…...

SpringBoot_mybatis-plus使用json字段

mybatis-plus使用json字段 1.前言2.方案分析2.1 为什么是json2.2 数据库的选择 3. 实战3.1 使用text字段(h2数据库)3.1.1 建表语句3.1.2 数据操作与查询 3.2 使用json字段(mysql数据库)3.2.1 建表语句3.2.2 数据操作与查询 4. 附录4.1 MySQL JSON索引用法4.2 mybatis-plus json…...

牛客出bug(华为机试HJ71)

Hj71&#xff1a;字符串通配符 描述 问题描述&#xff1a;在计算机中&#xff0c;通配符一种特殊语法&#xff0c;广泛应用于文件搜索、数据库、正则表达式等领域。现要求各位实现字符串通配符的算法。 要求&#xff1a; 实现如下2个通配符&#xff1a; *&#xff1a;匹配0个…...

第十一章 日志管理

第十一章 日志管理 1日志进程rsyslog 任务一 rsyslog 系统日志管理 ​ 关心问题 哪些程序产生的什么日志放到什么地方 任务一详解 1处理日志的进程 第一类 rsyslog 系统专职日志程序 处理绝大部分日志记录 系统操作有关的信息 如登录信息 程序启动关闭信息 错误喜喜 …...

灯串跨境外贸出口欧美CE认证和UL588报告周期解析

灯串灯具出口欧盟要做CE认证&#xff0c;CE认证需要做CE的两项检测,工作电压直流75V以上&#xff0c;交流50V以上 测试EMCLVD两项。 灯串LVD(安规&#xff09;标准为&#xff1a; 欧洲EN 60598-2-20:2015 1.标记 2.结构 3.爬电距离和电气间隙 4.接线端子 5.外部接线和内…...

大数据中的分布式文件系统MapReduce的选择题

一 . 选择题 一. 单选题&#xff08;共9题&#xff0c;49.5分&#xff09; (单选题)下列传统并行计算框架,说法错误的是哪一项? A. 刀片服务器、高速网、SAN,价格贵,扩展性差上 B. 共享式(共享内存/共享存储),容错性好 C. 编程难度高 D. 实时、细粒度计算、计算密集型 正确答…...

storm安装手册及笔记

图解Storm相关概念 图解storm的并发机制 安装Storm的步骤 1、安装一个zookeeper集群 2、上传storm的安装包&#xff0c;解压 3、修改配置文件storm.yaml #所使用的zookeeper集群主机 storm.zookeeper.servers: - "weekend05" - "weekend06"…...

vue 视频流播放

采用的技术是vueflv.js 前言 常见视频流格式 ● RTMP&#xff08;推流端、拉流端&#xff09; ● RTSP&#xff08;推流端&#xff09; ● HLS&#xff08;拉流端&#xff09; ● FLV&#xff08;拉流端&#xff09; 视频流是否依赖插件直播/点播协议web/移动端flv否直播点播…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...