day50 动态规划 198.打家劫舍 213.打家劫舍II 337.打家劫舍III

 198.打家劫舍

当前房屋偷与不偷取决于 前一个房屋和前两个房屋是否被偷了。

动规五部曲

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

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

2.确定递推公式

决定dp[i]的因素就是第i房间偷还是不偷。

如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。

如果不偷第i房间,那么dp[i] = dp[i - 1],即考 虑i-1房,(注意这里是考虑,并不是一定要偷i-1房,这是很多同学容易混淆的点

然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

3.dp数组如何初始化

从递推公式dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);可以看出,递推公式的基础就是dp[0] 和 dp[1]

从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);

4.确定遍历顺序

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

5.举例推导dp数组

示例,输入[2,7,9,3,1]为例。

代码

class Solution {
    public int rob(int[] nums) {
		if (nums == null || nums.length == 0) return 0;
		if (nums.length == 1) return nums[0];

		int[] dp = new int[nums.length];
		dp[0] = nums[0];
		dp[1] = Math.max(dp[0], nums[1]);
		for (int i = 2; i < nums.length; i++) {
			dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
		}

		return dp[nums.length - 1];
    }
}

 213.打家劫舍II  

思路:将成环的问题“展开”为线性问题

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

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

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

 

  • 情况二:考虑包含首元素,不包含尾元素(考虑并不是要取

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

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

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

代码

class Solution {
        public int rob(int[] nums) {
            if (nums == null || nums.length == 0)
                return 0;
            int len = nums.length;
            if (len == 1) return nums[0];
            return Math.max(robAction(Arrays.copyOfRange(nums, 0, nums.length - 1)),
                    robAction(Arrays.copyOfRange(nums, 1, nums.length)));
        }

        public int robAction(int[] nums) {
            if (nums.length == 1) {
                return nums[0];
            }
            if (nums.length == 2) {
                return Math.max(nums[0], nums[1]);
            }
            int length = nums.length;
            int[] dp = new int[length];
            dp[0] = nums[0];
            dp[1] = Math.max(nums[0], nums[1]);
            for (int i = 2; i < length; i++) {
                dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
            }

            return dp[length - 1];
        }
    }

337.打家劫舍III  

对于树的话,首先就要想到遍历方式,前中后序(深度优先搜索)还是层序遍历(广度优先搜索)。

本题一定是要后序遍历,因为通过递归函数的返回值来做下一步计算

如果抢了当前节点,两个孩子就不能动,如果没抢当前节点,就可以考虑抢左右孩子(注意这里说的是“考虑”

动态规划

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

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

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

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

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

长度为2的数组怎么标记树中每个节点的状态呢?

别忘了在递归的过程中,系统栈会保存每一层递归的参数。(每一层都会创建)

2.确定终止条件

在遍历的过程中,如果遇到空节点的话,很明显,无论偷还是不偷都是0,所以就返回,这也相当于dp数组的初始化

3.确定遍历顺序

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

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

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

4.确定单层递归的逻辑

如果是偷当前节点,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0]; (left,right就为dp数组

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

5.举例推导dp数组

dp数组状态如下:(注意用后序遍历的方式推导

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

代码

class Solution {
	// 状态标记递归
	// 不偷:Max(左孩子不偷,左孩子偷) + Max(右孩子不偷,右孩子偷)
	// 偷:左孩子不偷+ 右孩子不偷 + 当前节点偷
	public int rob(TreeNode root) {
		int[] res = robAction1(root);
		return Math.max(res[0], res[1]);
	}

	int[] robAction1(TreeNode root) {
		int res[] = new int[2];
		if (root == null)
			return res;

		int[] left = robAction1(root.left);
		int[] right = robAction1(root.right);

		res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
		res[1] = root.val + left[0] + right[0];
		return res;
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

结构体+结构体内存对齐+结构体实现位段

结构体内存对齐实现位段 一.结构体1.结构体的声明2.结构体变量成员访问操作符3.结构体传参4.匿名结构体5.结构的自引用 二.结构体内存对齐1.对齐规则2.为什么存在内存对齐&#xff1f;3.修改默认对齐数 三.结构体实现位段1.什么是位段2.位段的内存分配3.位段的跨平台问题4.位段…

SELinux深度解析:安全增强型Linux的探索与应用(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、SELinux概述 2、SELinux诞生背景 3、SELinux …

Django 视图探秘:FBV与CBV注册方式的异同,揭秘as_view()的执行魔法

文章目录 一、FBV、CBV注册方式及其区别FBVCBV 二、as_view()函数查看对应的view函数具体内容&#xff0c;最终返回的是dispatch方法查看dispatch方法 一、FBV、CBV注册方式及其区别 FBV FBV&#xff1a;path(index/,views.index) 通过调用函数方式&#xff0c;views.index是一…

打印机扫描工具V2.1发布

打印机扫描工具V2.1发布 从打印机扫描工具发布1.4版本以来&#xff0c;大家反馈了一些问题&#xff0c;目前就比较集中的问题&#xff0c;做了一些优化&#xff0c;做了一些大的调整&#xff0c;发布了2.1版本。 优化问题&#xff1a; 进一步优化安装包太大问题&#xff0c;…

上海亚商投顾:深成指、创业板指均涨超1%,电力股午后集体走强

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日低开后震荡反弹&#xff0c;深成指、创业板指均涨超1%&#xff0c;黄白二线依旧分化。电力、电网股午…

CHATGPT升级plus(已有账号前提下)

注册wildcard(虚拟卡) 注册号账号后先进行充值&#xff0c;充值后选择CHATGPT一键升级按照他的流程来即可 Wildcard网址&#xff1a;Wildcard跳转注册 填写邀请码充值时少两美金合计14&#xffe5; 邀请码&#xff1a;OL3QXTRH

挑战你的数据结构技能:复习题来袭【6】

1. (单选题)设无向图的顶点个数为n,则该图最多有&#xff08;&#xff09;条边 A. n-1 B. n(n-1)/2 C. n(n1)/2 D. 0 答案&#xff1a;B 分析&#xff1a; 2. (单选题)含有n个顶点的连通无向图,其边的个数至少为()。 A. n-1 B. n C. n1 D. nlog2n 答案&#xff1a;A…

10 数据封装与层次对应关系

一、TCP/IP模型 二、封装与解封装 &#xff08;一&#xff09;数据的封装 &#xff08;二&#xff09;数据的解封装 三、协议、数据与设备 &#xff08;一&#xff09;对应层次协议 结构协议应用层HTTP / FTP / TFTP / SMTP / SNMP/ DNS传输层TCP / UDP网络层ICMP / IGMP / …

使用记事本或者写字板打开中文乱码问题

最近下载一个开源的公共的文件&#xff0c;下载下来是xml格式的文本文件&#xff0c;然后我尝试打开&#xff0c;使用记事本打开文件&#xff0c;内容显示正常&#xff0c;但是因为是xml文件&#xff0c;使用记事本打开的时候没有换行&#xff0c;不方便看&#xff0c;然后就使…

信息系统项目管理师0143:过程概述(9项目范围管理—9.2项目范围管理过程—9.2.1过程概述)

点击查看专栏目录 文章目录 9.2 项目范围管理过程9.2.1 过程概述 9.2 项目范围管理过程 9.2.1 过程概述 项目范围管理过程包括&#xff1a; 规划范围管理&#xff1a;为了记录如何定义、确认和控制项目范围及产品范围&#xff0c;创建范围管理计划。收集需求&#xff1a;为了…

文章自动排版

文字太多了不想看怎么办&#xff1f;想快速提取并罗列文章的重点要如何操作&#xff1f;今天给大家介绍一下如何把复杂的文章总结为一个个观点 使用说明 打开智游剪辑&#xff08;zyjj.cc&#xff09;&#xff0c;搜索文字排版 我们输入要排版的文章&#xff0c;点击立即生成就…

心链9----组队功能开发以及请求参数包装类和包装类实现

心链 — 伙伴匹配系统 组队功能开发 需求分析 理想的应用场景 我要跟别人一起参加竞赛或者做项目&#xff0c;可以发起队伍或者加入别人的队伍 用户可以 创建 一个队伍&#xff0c;设置队伍的人数、队伍名称&#xff08;标题&#xff09;、描述、超时时间 P0 队长、剩余的人数…

安防综合管理系统EasyCVR视频汇聚平台GA/T 1400协议中的关键消息交互示例

在当今的信息化时代&#xff0c;公共安全防范日益成为保障社会和谐稳定的关键。视频监控系统作为现代安全防范的重要手段&#xff0c;正不断在公安、交通、城市管理等领域发挥着越来越重要的作用。而GA/T 1400协议视图库&#xff0c;作为公安视频图像信息应用系统的标准&#x…

使用 TinyEngine 低代码引擎实现三方物料集成

本文由体验技术团队 TinyEngine 项目成员炽凌创作&#xff0c;欢迎大家实操体验&#xff0c;本体验内容基于 TinyEngine 低代码引擎提供的环境&#xff0c;介绍了如何通过 TinyEngine 低代码引擎实现三方物料集成&#xff0c;帮助开发者快速开发。 知识背景 1.1 TinyEngine 低…

江苏省汽车及零部件产业协作配套对接会在苏州举行

5月28日&#xff0c;江苏省汽车及零部件产业协作配套对接会暨“百场万企”大中小企业融通对接活动在苏州举办。本次活动以“深化整零协作&#xff0c;促进大中小企业融通发展”为主题&#xff0c;由江苏省工业和信息化厅、中国中检所属中国汽车工程研究院股份有限公司&#xff…

Linux系统Docker部署Apache Superset并实现远程访问详细流程

目录 前言 1. 使用Docker部署Apache Superset 1.1 第一步安装docker 、docker compose 1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网穿透&#xff0c;实现公网访问 3. 设置固定连接公网地址 前言 作者简介&#xff1a; 懒大王敲代码&#xff0…

Python第二语言(一、Python start)

目录 1、下载Pyhton注意 2、python下载 3、Python start 3.1 第一个python&#xff08;print("Hello World!")&#xff09; 3.2 执行多条python代码&#xff08;Python解释器&#xff09; 3.3 小结&#xff08;python解释器、.py文件&#xff09; 3.4 开发工具…

Java微服务智慧工地可视化SaaS云解决方案源码

智慧工地是指运用信息化手段&#xff0c;围绕施工过程管理&#xff0c;建立互联协同、智能生产、科学管理的施工项目信息化生态圈&#xff0c;并将此数据在虚拟现实环境下与物联网采集到的工程信息进行数据挖掘分析&#xff0c;提供过程趋势预测及专家预案&#xff0c;实现工程…

计算机基础(8)——音频数字化(模电与数电)

&#x1f497;计算机基础系列文章&#x1f497; &#x1f449;&#x1f340;计算机基础&#xff08;1&#xff09;——计算机的发展史&#x1f340;&#x1f449;&#x1f340;计算机基础&#xff08;2&#xff09;——冯诺依曼体系结构&#x1f340;&#x1f449;&#x1f34…

Springboot 开发-- 集成 Activiti 7 流程引擎

引言 Activiti 7是一款遵循BPMN 2.0标准的开源工作流引擎&#xff0c;旨在为企业提供灵活、可扩展的流程管理功能。它支持图形化的流程设计、丰富的API接口、强大的执行引擎和完善的监控报表&#xff0c;帮助企业实现业务流程的自动化、规范化和智能化。本文将为您详细介绍 Ac…