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

DAY39|动态规划Part07|LeetCode:198.打家劫舍、213.打家劫舍II、337.打家劫舍III

目录

LeetCode:198.打家劫舍

基本思路

C++代码

LeetCode:213.打家劫舍II

基本思路

C++代码

LeetCode:337.打家劫舍III

基本思路

C++代码


LeetCode:198.打家劫舍

力扣题目链接

文字讲解:LeetCode:198.打家劫舍

视频讲解:动态规划,偷不偷这个房间呢?

基本思路

        看到这个问题,很容易想到,需要对当前房屋偷与不偷两种状态进行判断,而这个状态和前一个房间和前两个房间是否被偷有很大的关系

        通过动规五部曲进行分析:

  • 确定dp数组(dp table)以及下标的含义

        dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]

  • 确定递推公式

        首先决定dp[i]的因素就是第i房间偷还是不偷。而如果偷了第i个房间,那么其偷盗金额就和前两个房间有关;如果不偷第i个房间,显然dp[i]和前一个房间的金额相同。

        因此容易推出递推公式为:dp[i] = max(dp[i-1],dp[i-2]+nums[i]);

  • dp数组如何初始化

        因为题目明确说明街道上存在一个以上的房屋,当街道上只有一个房屋时,我们直接返回nums[0],如果大于等于两个房屋时,我们令dp[0]为nums[0],令dp[1] = max(nums[0],nums[1]);

  • 确定遍历顺序

        dp[i] 是根据dp[i - 2] 和 dp[i - 1] 推导出来的,那么一定是从前到后遍历!

for (int i = 2; i < nums.size(); i++) {dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
}
  • 举例推导dp数组

以示例二,输入[2,7,9,3,1]为例,红框dp[nums.size() - 1]为结果。

C++代码

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());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];}
};

LeetCode:213.打家劫舍II

力扣题目链接

文字讲解:LeetCode:213.打家劫舍II

视频讲解:动态规划,房间连成环了那还偷不偷呢?

基本思路

        这个题目相对于上一个题目,不同点在于街道上的房子练成了一个圈,那么我们到底应不应该选择第一个房屋和最后一个房屋呢?

        很容易想到可以分成三种情况:

  • 情况一:考虑不包含首尾元素

  • 情况二:考虑包含首元素,不包含尾元素

  • 情况三:考虑包含尾元素,不包含首元素

        而在情况二和情况三种我们提到可以考虑包含首尾元素,而不是一定包含,因此情况一的情形实际上是包含在情况二和情况三中的。

        这个样子我们和容易和上个题目中的动规五部曲进行相同的分析了。无非就是进行判断的区间有所不同。

C++代码

// 注意注释中的情况二情况三,以及把198.打家劫舍的代码抽离出来了
class Solution {
public:int rob(vector<int>& nums) {if (nums.size() == 0) return 0;if (nums.size() == 1) return nums[0];int result1 = robRange(nums, 0, nums.size() - 2); // 情况二int result2 = robRange(nums, 1, nums.size() - 1); // 情况三return max(result1, result2);}// 198.打家劫舍的逻辑int robRange(vector<int>& nums, int start, int end) {if (end == start) return nums[start];vector<int> dp(nums.size());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];}
};

LeetCode:337.打家劫舍III

力扣题目链接

文字讲解:LeetCode:337.打家劫舍III

视频讲解:动态规划,房间连成树了,偷不偷呢?

基本思路

        这个题目结合了二叉树的相关知识,如果忘记了的同学可以重新回顾一下二叉树相关的知识和题目。这个题目当然也可以使用二叉树递归的方法进行求解,但是我们知道二叉树的时间复杂度远大于动态规划的时间复杂度,这就很容易导致出现超时的情况。

        这道题目算是树形dp的入门题目,因为是在树上进行状态转移,我们在讲解二叉树的时候说过递归三部曲,那么下面我以递归三部曲为框架,其中融合动规五部曲的内容来进行讲解

  • 确定递归函数的参数和返回值

        我们需要传入的是根节点,而返回的是所能偷到的最大金额,因此返回值是int类型。对于每个二叉树节点,我们需要求出对于当前节点偷与不偷两个状态。我们还需要设置一个函数,用来记录每个节点偷与不偷状态下所能获得的最大金额。传入的为当前节点的指针,返回为一个数组。

int rob(TreeNode* root)
vector<int> robTree(TreeNode* cur)
  • 确定终止条件

        对二叉树的所有节点进行遍历,当节点为空节点时,表示无论是否偷空节点,偷到的金额都为零,此时返回{0,0}。

if (cur == NULL) return vector<int>{0, 0};
  • 确定遍历顺序

        因为是否偷当前节点需要根据是否偷左右孩子获得的最大金额决定。因此需要先遍历左右孩子,在遍历中间节点,即遍历方式采用后序遍历。

  • 确定单层递归的逻辑

        遍历当前节点时,如果偷当前节点,那么就不能偷左右孩子,即取left[0]和right[0];如果不偷当前节点,那么就对左右节点是否偷盗的可以获得的金额求最大值。

vector<int> left = robTree(cur->left); // 左
vector<int> right = robTree(cur->right); // 右// 偷cur
int val1 = cur->val + left[0] + right[0];
// 不偷cur
int val2 = max(left[0], left[1]) + max(right[0], right[1]);
return {val2, val1};
  • 举例推导dp数组

        以示例1为例,dp数组状态如下:

        最后头结点就是 取下标0 和 下标1的最大值就是偷得的最大金钱

C++代码

class Solution {
public:int rob(TreeNode* root) {vector<int> result = robTree(root);return max(result[0], result[1]);}// 长度为2的数组,0:不偷,1:偷vector<int> robTree(TreeNode* cur) {if (cur == NULL) return vector<int>{0, 0};vector<int> left = robTree(cur->left);vector<int> right = robTree(cur->right);// 偷cur,那么就不能偷左右节点。int val1 = cur->val + left[0] + right[0];// 不偷cur,那么可以偷也可以不偷左右节点,则取较大的情况int val2 = max(left[0], left[1]) + max(right[0], right[1]);return {val2, val1};}
};

相关文章:

DAY39|动态规划Part07|LeetCode:198.打家劫舍、213.打家劫舍II、337.打家劫舍III

目录 LeetCode:198.打家劫舍 基本思路 C代码 LeetCode:213.打家劫舍II 基本思路 C代码 LeetCode:337.打家劫舍III 基本思路 C代码 LeetCode:198.打家劫舍 力扣题目链接 文字讲解&#xff1a;LeetCode:198.打家劫舍 视频讲解&#xff1a;动态规划&#xff0c;偷不偷这个…...

MYSQL----------------sql 优化

优化 SQL 语句的一般步骤 1. 了解 SQL 的执行频率 SHOW STATUS LIKE Com_%;代码解释&#xff1a; SHOW STATUS LIKE Com_%;&#xff1a;此命令可以查看各种 SQL 语句的执行频率&#xff0c;例如 Com_select 表示 SELECT 语句的执行次数&#xff0c;Com_insert 表示 INSERT 语…...

深度学习中的正则化方法

最近看到了正则化的内容&#xff0c;发现自己对正则化的理解已经忘得差不多了&#xff0c;这里在整理一下&#xff0c;方便以后查阅。 深度学习中的正则化方法 1. L2 正则化&#xff08;L2 Regularization&#xff09;2. L1 正则化&#xff08;L1 Regularization&#xff09;3.…...

前端报告 2024:全新数据,深度解析未来趋势

温馨提示: 此报告为国际版全球报告,其中所涉及的技术应用、工具偏好、开发者习惯等情况反映的是全球前端开发领域的综合态势。由于国内外技术发展环境、行业生态以及企业需求等存在差异,可能有些内容并不完全契合国内的实际情况,请大家理性阅读,批判性地吸收其中的观点与信…...

计算机网络之---子网划分与IP地址

子网划分与IP地址的关系 在计算机网络中&#xff0c;子网划分&#xff08;Subnetworking&#xff09;是将一个网络划分为多个子网络的过程。通过子网划分&#xff0c;可以有效地管理和利用IP地址空间&#xff0c;提高网络的性能、安全性和管理效率。 子网划分的基本目的是通过…...

计算机网络 (31)运输层协议概念

一、概述 从通信和信息处理的角度看&#xff0c;运输层向它上面的应用层提供通信服务&#xff0c;它属于面向通信部分的最高层&#xff0c;同时也是用户功能中的最低层。运输层的一个核心功能是提供从源端主机到目的端主机的可靠的、与实际使用的网络无关的信息传输。它向高层用…...

代码随想录算法训练营day28

代码随想录算法训练营 —day28 文章目录 代码随想录算法训练营前言一、122.买卖股票的最佳时机II二、55. 跳跃游戏三、跳跃游戏 II方法一方法二 1005. K 次取反后最大化的数组和总结 前言 今天是算法营的第28天&#xff0c;希望自己能够坚持下来&#xff01; 今日任务&#x…...

建立时间和保持时间

建立时间 在时钟有效沿到来之前&#xff0c;数据必须维持一段时间保持不变&#xff0c;这段时间就是建立时间 Tsetup 1 基本概念 建立时间&#xff08;Setup Time&#xff09;&#xff1a; 在 SystemVerilog 中&#xff0c;建立时间是指在时钟信号的有效边沿&#xff08;例如…...

vue,router路由传值问题,引用官方推荐

参考贴https://blog.csdn.net/m0_57033755/article/details/129927829 根据官方文档的更新日志&#xff0c;建议使用state传值 官方文档更新日志 实际的console结果 传值 router.push({ name: KnowledgeDetail, state: { params } });接收值 const historyParams histor…...

AIDD-人工智能药物设计-AlphaFold系列:年终回顾,AlphaFold迄今为止的实际应用案例

AlphaFold系列&#xff1a;年终回顾&#xff0c;AlphaFold迄今为止的实际应用案例 01 引言 AlphaFold由 DeepMind 团队开发&#xff0c;最初在蛋白质结构预测竞赛 CASP 中惊艳亮相。随着 AlphaFold2 和后续版本的迭代进步&#xff0c;其精度和通用性不断提升&#xff0c;逐渐走…...

Scala语言的面向对象编程

Scala语言的面向对象编程 引言 在当今的软件开发中&#xff0c;面向对象编程&#xff08;OOP&#xff09;是一种非常强大且广泛使用的编程范式。Scala是一种现代编程语言&#xff0c;结合了面向对象编程和函数式编程的特性&#xff0c;非常适合用于大规模软件的开发。本文将介…...

MySQL学习记录1【DQL和DCL】

SQL学习记录 该笔记从DQL处开始记录 DQL之前值得注意的点 字段 BETWEEN min AND max 可以查询区间[min, max]的数值如果同一个字段需要满足多个OR条件&#xff0c;可以采取 字段 IN(数值1, 数值2, 数值3....)LIKE语句 字段 LIKE ___%%% 表示模糊匹配&#xff0c;_匹配一个字段…...

验证码转发漏洞

开发人员有时候会以数组的形式接收用户的手机号并遍历执行&#xff0c;这时就可以在注册或登录页面填写两个手机号并点击发送验证码&#xff0c;这两个手机号会同时收到相同验证码&#xff0c;可以用任意一个手机号登录或注册&#xff0c;即验证码转发漏洞。 1、burpsuite内置…...

使用 C++ 实现神经网络:从基础到高级优化

引言 在现代机器学习中&#xff0c;神经网络已经成为最重要的工具之一。虽然 Python 提供了诸如 TensorFlow、PyTorch 等强大的机器学习库&#xff0c;但如果你想深入理解神经网络的实现原理&#xff0c;或者出于某些性能、资源限制的考虑&#xff0c;使用 C 来实现神经网络会是…...

【WRF运行报错】总结WRF运行时报错及解决方案(持续更新)

目录 ./real.exe错误1:ERROR while reading namelist physics./wrf.exe错误1:FATAL CALLED FROM FILE: <stdin> LINE: 2419 Warning: too many input landuse types参考./real.exe 错误1:ERROR while reading namelist physics 执行./real.exe时,报错如下: taski…...

Kotlin语言的循环实现

Kotlin语言中的循环实现 Kotlin是一种现代的、跨平台的编程语言&#xff0c;广泛应用于Android开发、后端服务及多种其他软件开发领域。与Java类似&#xff0c;Kotlin也支持多种循环结构&#xff0c;包括for循环、while循环和do while循环。掌握这些循环结构是每个Kotlin开发者…...

基于CNN的人脸识别考勤管理系统实现

随着技术的不断进步&#xff0c;人脸识别技术已经在各行各业得到了广泛的应用&#xff0c;尤其在 考勤管理 上&#xff0c;它提供了更加智能、便捷、精准的解决方案。本篇博客将介绍如何基于 PyQt5 和 MySQL 实现一个 人脸识别考勤系统&#xff0c;并通过具体代码展示如何通过图…...

Android基于回调的事件处理

Android 中的回调机制&#xff1a;基于回调的事件处理详解 在 Android 开发中&#xff0c;回调&#xff08;Callback&#xff09;是一种常见的事件处理机制&#xff0c;主要用于异步操作和事件通知。与传统的基于监听器的事件处理相比&#xff0c;回调机制更加灵活、通用&…...

postgis和地理围栏

postgis postgis是pg数据库的一个插件&#xff0c;除原数据类型外(int varchar)、新增了空间数据类型(geography和geometry)。比如我们新建一张道路表road(字段有名称varchar、建设时间timestamp、地理位置geometry)&#xff0c;可以将道路名字、建设时间存进去&#xff0c;同…...

《鸿蒙系统AI技术:筑牢复杂网络环境下的安全防线》

在当今数字化时代&#xff0c;复杂网络环境给智能系统带来了诸多安全挑战&#xff0c;而鸿蒙系统中的人工智能技术却展现出强大的安全保障能力&#xff0c;为用户在复杂网络环境中的安全保驾护航。 微内核架构&#xff1a;安全基石 鸿蒙系统采用微内核架构&#xff0c;将核心…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...