刷题DAY48 | LeetCode 198-打家劫舍 213-打家劫舍II 337-打家劫舍III

198 打家劫舍(medium)

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

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

思路:动态规划法

代码实现:

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];}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

详细解析:
思路视频
代码实现文章


213 打家劫舍II(medium)

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

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

思路:动态规划法,分解为两个子问题

这道题目和198.打家劫舍是差不多的,唯一区别就是成环了。

对于一个数组,成环的话主要有如下三种情况:

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

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

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

注意是"考虑",例如情况三,虽然是考虑包含尾元素,但不一定要选尾部元素! 对于情况三,取nums[1] 和 nums[3]就是最大的。

而情况二 和 情况三 都包含了情况一了,所以只考虑情况二和情况三就可以了。

分析到这里,本题其实比较简单了。 剩下的和198.打家劫舍就是一样的了。

代码实现:

// 注意注释中的情况二情况三,以及把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];}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

详细解析:
思路视频
代码实现文章


337 打家劫舍III(medium)

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。

思路:动态规划法+递归算法

动态规划其实就是使用状态转移容器来记录状态的变化,这里可以使用一个长度为2的数组,记录当前节点偷与不偷所得到的的最大金钱。

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

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

这里我们要求一个节点 偷与不偷的两个状态所得到的金钱,那么返回值就是一个长度为2的数组。

参数为当前节点,代码如下:

vector<int> robTree(TreeNode* cur) {

其实这里的返回数组就是dp数组。

所以dp数组(dp table)以及下标的含义:下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。

所以本题dp数组就是一个长度为2的数组!

长度为2的数组怎么标记树中每个节点的状态呢?别忘了在递归的过程中,系统栈会保存每一层递归的参数。

  1. 确定终止条件

在遍历的过程中,如果遇到空节点的话,很明显,无论偷还是不偷都是0,所以就返回

if (cur == NULL) return vector<int>{0, 0};

这也相当于dp数组的初始化

  1. 确定遍历顺序

首先明确的是使用后序遍历。 因为要通过递归函数的返回值来做下一步计算。

通过递归左节点,得到左节点偷与不偷的金钱。

通过递归右节点,得到右节点偷与不偷的金钱。

代码如下:

// 下标0:不偷,下标1:偷
vector<int> left = robTree(cur->left); // 左
vector<int> right = robTree(cur->right); // 右
// 中
  1. 确定单层递归的逻辑
  • 如果是偷当前节点,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0]; \

  • 如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);

最后当前节点的状态就是{val2, val1}; 即:{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}

代码如下:

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};
  1. 举例推导dp数组
    以示例1为例,dp数组状态如下:(注意用后序遍历的方式推导)
    在这里插入图片描述

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

代码实现:

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};}
};
  • 时间复杂度:O(n),每个节点只遍历了一次
  • 空间复杂度:O(log n),算上递推系统栈的空间

详细解析:
思路视频
代码实现文章

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

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

相关文章

Linux笔记-对xargs的理解(2023-12-13)

此篇记录在个人笔记库的时间是2023-12-13&#xff0c;公布到互联网上的时间是2024-04-09 这个命令最开始是在5年前看人用过&#xff0c;当时不太理解&#xff0c;最近又看到有人在用&#xff0c;突然间就通了&#xff0c;也查阅了点资料&#xff0c;记录下这个笔记&#xff1a…

吴恩达深度学习笔记:深层神经网络(Deep Neural Networks)4.5-4.8

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第四周&#xff1a;深层神经网络(Deep Neural Networks)4.5 为什么使用深层表示&#xff1f;&#xff08;Why deep representations?&#xff09; 第一门课&#xff1a;神经网络和深度学习 (…

CKA 基础操作教程(五)

Kubernetes Ingress 理论学习 Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。 Ingress 资源示例&#xff1a; apiVersion: networking.k8s.io/v1 # 指定 Kubernetes 中使用的 API 版本 kind: Ingress # 指定对象…

c语言 :柔性数组与c/c++内存领域的划分

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一 柔性数组&#xff08;1&#xff09;什么是柔性数组1&#xff09;柔性数组的声明2&#xff09;柔性数组的特性 &#xff08;2&#xff09;柔性数组的使用 二 c/c内…

APx500音频分析仪硬件简介

两通道模拟输出&#xff0c;两通道或以上的模拟输入接口 线性编码数字音频接口&#xff08;AES/EBU,TOSLINK,SPDIF&#xff09;Linear PCM 脉冲密度调制码流&#xff08;需要APx-PDM选件支持&#xff09; Bluetooth蓝牙音频码流&#xff08;需APx-BT选件支持&#xff09; 最…

用二八定律分析零售数据,不就更直观了吗?

20%的商品贡献了80%的销售金额&#xff0c;你会不会想知道这些商品的销售金额、毛利、销售金额累计占比、毛利累计占比&#xff0c;会不会想知道这些商品在各个门店的销售表现&#xff1f;看是否能进一步提高销售金额&#xff0c;提高毛利。这样的报表该怎么做&#xff1f;奥威…

Ceph学习 -4.Ceph组件介绍

文章目录 1.Ceph组件介绍1.1 组件介绍1.2 流程解读1.2.1 综合效果图1.2.2 数据存储逻辑 1.3 小结 1.Ceph组件介绍 学习目标&#xff1a;这一节&#xff0c;我们从组件介绍、流程解读、小结三个方面来学习。 1.1 组件介绍 无论是想向云平台提供 Ceph 对象存储和 Ceph 块设备服务…

Xinstall助力提升用户体验:一键打开App用户页面

在移动互联网时代&#xff0c;App已经成为我们日常生活中不可或缺的一部分。然而&#xff0c;随着App数量的激增&#xff0c;如何让用户更便捷地打开和使用App&#xff0c;提升用户体验&#xff0c;成为了开发者和广告主们亟待解决的问题。此时&#xff0c;Xinstall作为国内专业…

[Linux][权限][粘滞位]详细解读,深入了解Linux权限

1.Linux权限的概念 Linux下有两种用户&#xff1a;超级用户(root)、普通用户 超级用户&#xff1a;可以在Linux系统下做任何事情&#xff0c;不受限制普通用户&#xff1a;在Linux下做有限的事情&#xff0c;可以有多个超级用户的命令提示符是**“#”&#xff0c;普通用户的命…

Linux中磁盘管理

一.磁盘管理的概括和简要说明 磁盘空间的管理&#xff0c;使用硬盘三步&#xff1a; &#xff08;1&#xff09;分区&#xff1a; &#xff08;2&#xff09;安装文件系统格式化 &#xff08;3&#xff09;挂载&#xff1a; 硬盘的分类&#xff1a; &#xff08;1&#x…

基于单片机自动增益放大电路0-3倍系统

**单片机设计介绍&#xff0c;基于单片机自动增益放大电路0-3倍系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机自动增益放大电路0-3倍系统是一个电子工程领域的创新设计&#xff0c;它结合了单片机技术和自动增益…

安卓开机启动流程

目录 一、整体框架二、流程代码分析2.1 Boot ROM2.2 Boot Loader2.3 Kernel层Kernel代码部分 2.4 Init进程Init进程代码部分 2.5 zygote进程zygote代码部分 2.6 SystemServer进程SystemServer代码部分 2.7 启动Launcher与SystemUI 三、SystemServices3.1 引导服务3.2 核心服务3…

Openstack(T)部署ceilometer-gnocchi-panko-aodh

前言&#xff1a;简单概述4个服务做什么&#xff0c;如何协同起来 ceilometer负责采集数据&#xff0c;采集的数据分为计量数据和事件数据&#xff0c;计量数据交给gnocchi处理(本文gnocchi将计量数据存储在ceph存储池中)&#xff0c;事件数据存储在panko中&#xff0c;aodh负…

Flink内存模型

1、Flink进程内存模型 配置项 TaskManager 配置参数 JobManager 配置参数 Flink 总内存taskmanager.memory.flink.sizejobmanager.memory.flink.size进程总内存taskmanager.memory.process.sizejobmanager.memory.process.size 2、Task Managers内存模型 组成部分 配…

C#操作MySQL从入门到精通(7)——对查询数据进行简单过滤

前言 我们在查询数据库中数据的时候,有时候需要剔除一些我们不想要的数据,这时候就需要对数据进行过滤,比如学生信息中,我只需要年龄等于18的,类似这种操作,本文就是详细介绍如何对查询的数据进行初步的过滤。 1、等于操作符 本次查询student_age 等于20的数据,使用我…

python 08Pandas

1.基础概念 2.基本操作 &#xff08;1&#xff09;加载数据集 import pandas as pd #引入pandas包 打开csv文件 df pd.read_csv(./data/gapminder.tsv,sep\t) #\t制表符&#xff0c;即tab&#xff0c;缩进四个字符 \n表示回车换行 print(type(df)) print(df.head()) #…

政安晨:【Keras机器学习实践要点】(二十二)—— 基于 TPU 的肺炎分类

目录 简述 介绍 / 布置 加载数据 可视化数据集 建立 CNN 纠正数据失衡 训练模型 拟合模型 可视化模型性能 ​编辑预测和评估结果 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客…

你知道哪几种当前流行的lisp语言的方言?

估计很多人都看过《黑客与画家》这本书&#xff0c;这本书主要介绍黑客即优秀程序员的爱好和动机&#xff0c;讨论黑客成长、黑客对世界的贡献以及编程语言和黑客工作方法等所有对计算机时代感兴趣的人的一些话题。作者保罗格雷厄姆字里行间不经意间向大家推介Lisp是最好的编程…

Laravel 项目如何运行

如有一个 Laravel 项目&#xff0c;在配置好 PHP 版本和运行环境后&#xff0c;可以直接在项目下直接运行&#xff1a; php artisan serve 来启动你的项目。 通过浏览器查看 当项目运行后&#xff0c;默认的启动端口为 8000&#xff0c;可以通过浏览器来进行查看运行的 Larav…

二维数组及其内存图解

二维数组 在一维数组的介绍当中曾说&#xff0c;数组中可以储存任何同类型的元素&#xff0c;那么这个元素是不是可以也是数组呢&#xff1f;答案是可以&#xff0c;即在数组之中储存数组元素。这种情况就是多维数组&#xff0c;当一个数组中的元素是数组时叫做二维数组&#x…