java数据结构与算法刷题-----LeetCode337. 打家劫舍 III

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

    • 1. 动态规划+深度优先
      • 1.1 解题思路和细节
      • 2.2 代码实现

很多人觉得动态规划很难,但它就是固定套路而已。其实动态规划只不过是将多余的步骤,提前放到dp数组中(就是一个数组,只不过大家都叫它dp),达到空间换时间的效果。它仅仅只是一种优化思路,因此它目前的境地和线性代数一样----虚假的难。

  1. 想想线性代数,在国外留学的学生大多数不觉得线性代数难理解。但是中国的学生学习线性代数时,完全摸不着头脑,一上来就是行列式和矩阵,根本不知道这玩意是干嘛的。
  2. 线性代数从根本上是在空间上研究向量,抽象上研究线性关系的学科。人家国外的教科书都是第一讲就帮助大家理解研究向量和线性关系。
  3. 反观国内的教材,直接把行列式搞到第一章。搞的国内的学生在学习线性代数的时候,只会觉得一知半解,觉得麻烦,完全不知道这玩意学来干什么。当苦尽甘来终于理解线性代数时干什么的时候,发现人家国外的教材第一节就把这玩意讲清楚了。你只会大骂我们国内这些教材,什么狗东西(以上是自己学完线性代数后的吐槽,我们同学无一例外都这么觉得)。

而我想告诉你,动态规划和线性代数一样,我学完了才知道,它不过就是研究空间换时间,提前将固定的重复操作规划到dp数组中,而不用暴力求解,从而让效率极大提升。

  1. 但是网上教动态规划的兄弟们,你直接给一个动态方程是怎么回事?和线性代数,一上来就教行列式和矩阵一样,纯属恶心人。我差不多做了30多道动态规划题目,才理解,动态方程只是一个步骤而已,而这已经浪费我很长时间了,我每道题都一知半解不理解,过程及其痛苦。最后只能重新做。
  2. 动态规划,一定是优先考虑重复操作与dp数组之间的关系,搞清楚后,再提出动态方程。而你们前面步骤省略了不讲,一上来给个方程,不是纯属扯淡吗?
  3. 我推荐研究动态规划题目,按5个步骤,从上到下依次来分析
  1. DP数组及下标含义
  2. 递推公式
  3. dp数组初始化
  4. 数组遍历顺序(双重循环及以上时,才考虑)
  5. dp数组打印,分析思路是否正确(相当于做完题,检查一下)

在这里插入图片描述

1. 动态规划+深度优先

1.1 解题思路和细节

题目细节
  1. 想要偷到最多的钱,一定要遵循,适当取舍
  2. 比如上一个结点没偷,那么这个结点也不一定非要偷,因为你这个不偷,下一个就可以偷。
  3. 所以使用深度优先遍历,对于每个结点,都有两个选择,偷与不偷,而相邻的多个结点直接,不用非得隔一个偷一个,而是选择最大的方案。

比如100,1,2,3,4,100. 如果隔一个偷一个的话为100,1,2,3,4 = 106,100或100,1,2,3,4,100 = 104,但是如果是100,1,2,3,4,100 = 203明显是最大的方案.

  1. 特别注意:无论选择偷与不偷,都需要将左右子结点相加,因为只是相邻的结点不能偷,而不是整个子树都不能偷
图解
  1. 以此为例:其中dp数组含义是dp[当前结点偷的话当前共偷多少,不偷共偷多少]
    在这里插入图片描述
  2. 对于深度优先遍历的第一个结点为,左下角的3
    在这里插入图片描述
  1. 它的左子树是null,所以左子树偷与不偷都是0元,故其左子树的dp数组为dp[0,0],表示左子树偷的话共偷0元,不偷的话共偷0元
  2. 它的右子树是null,一样偷不偷都是0,故其右子树dp为dp[0,0]
  3. 它本身是3,所以偷的话就是+3.不偷的话就不加3
  1. 偷当前结点,那么左子树和右子树都不能偷,左子树不偷的话是0,右子树不偷也是0,合起来为0+0=0,因为都是0,所以就拿到0.加上当前结点3 共偷3元
  2. 不偷当前结点,那么左子树和右子树可以偷,左子树偷根结点和不偷都有0,右子树偷也是0,两棵子树都选最大的,合起来为0+0=0,当前结点也不偷,共偷0元
  1. 最终得到当前结点dp数组为dp[3,0],表示偷当前结点,不能偷两个直接儿子共获取3元,不偷当前结点偷左右儿子结点可偷0元
  1. 第二个遍历结点为它上面的2
    在这里插入图片描述
  1. 左子树为null,偷和不偷可获利[0,0]
  2. 右子树为3,偷和不偷分别获利[3,0]
  3. 当前结点如果偷,则+2,不偷则不加
  1. 偷当前结点,则左子树和右子树不能偷,左子树不偷为0,右子树不偷为0,合起来为0,则偷当前结点+2,获利2元
  2. 不偷当前结点,则左子树和右子树可以偷,左子树偷和不偷都为0,右子树偷为3,不偷为0,左右子树都选大的方案合为0+3 = 3,则不偷当前结点,获利3
  1. 因此当前结点dp为dp[2,3],表示偷当前结点的话,一共获利2元,不偷当前节点,共获利3元
  1. 第3个遍历的结点是右下角的1,同理,左右子树都为null,则偷当前结点为1,不偷为0,故dp[1,0]
  2. 第4个遍历的是右下角1的父结点3,同理,左子树为null,右子树为1,dp[1,0],故当前结点dp[3,1].表示偷当前结点,下面1不偷,为3.不偷当前结点,偷下面那个1为1
  3. 最后是根结点3
    在这里插入图片描述
  1. 如果偷当前结点
  1. 则左子结点不能偷,左子结点dp为[2,3],也就是不偷它,共有为3
  2. 右子结点也不能偷,为1
  3. 则,偷当前结点的3,加上左子结点不偷共有3,右子结点不偷共有1,加起来为7.
  1. 不偷当前结点
  1. 左子结点可以偷也可以不偷,偷有2,不偷为3,选大的3
  2. 右子结点,偷有3,不偷为1,选大的共有3
  3. 不偷当前结点为0,加上左子结点不偷,共有3,右子结点偷,共有3。加起来为6
  1. 故,根节点dp为dp[7,6]
  1. 最终,因为我们要偷最多的钱,所以选择dp[7,6]中大的那个,为7
动态规划5步曲
  1. DP数组及下标含义
  1. 我们要求出的是二叉树相邻结点不能都偷的情况下,最多偷多少钱。显然dp数组中存储的是相邻结点如果偷,能偷多少钱,不偷相邻的,而偷当前结点能有多少钱。要求出谁的?显然是求出,以当前结点来看,前面一个结点偷还是不偷。那么下标就是代表前一个结点偷还是不偷,很显然,只需要一个下标,也就是一维数组。而且这个一维数组只有两个元素,代表偷和不偷
  1. 递推公式
  1. 假设left[a,b]表示左子树中偷了左儿子,共有left[a]元,不偷左儿子,共有left[b]元,同理right[a,b]为右子树
  2. 当前结点偷的话,左右儿子不能偷,不偷左儿子为left[b],不偷右儿子为right[b]。
  3. 当前结点不偷,左右儿子可以偷也可以不偷,偷左儿子为left[a],不偷为left[b],偷右儿子为right[a],不偷为right[b]
  4. 故dp[n] = [本身 + left[b] + right[b] ,max{ left[a] , left[b] } + max{ right[a] , right[b] }.也就是当前结点,偷的话,就是本身+左子树不偷左儿子+右子树不偷右儿子。不偷当前结点,就是左子树偷左儿子或不偷左儿子选大的+右子树偷或不偷右儿子选大的
  1. dp数组初始化

在这里插入图片描述

  1. 数组遍历顺序(单重循环,无需考虑遍历顺序,一共就一维,哪里来的谁先谁后)
  2. 打印dp数组(自己生成dp数组后,将dp数组输出看看,是否和自己预想的一样。)

在这里插入图片描述

2.2 代码实现

代码

在这里插入图片描述

class Solution {
    public int rob(TreeNode root) {
        int[] dp = dfs(root);//获取dp数组
        return Math.max(dp[0],dp[1]);//返回最后一个房子偷与不偷,最大的结果
    }
    //int[]{偷当前结点最大获利,不偷当前结点最大获利}
    int[] dfs(TreeNode root){
        if (root == null)return new int[]{0,0};//如果没的遍历,就返回0,0,表示偷和不偷当前结点都是获利0,因为没有这个房子
        int[] left = dfs(root.left);//获取左子树dp数组
        int[] right = dfs(root.right);//获取右子树dp数组
        //如果偷当前结点,则只有一种选择,就是不偷左右子树根节点
        int yes = root.val+ left[1] + right[1];
        //如果不偷当前房子,则左右子树都需要偷
        //左子树我们偷根结点,和不偷根节点,选大的
        //右子树我们也可以选择偷根节点,或不偷,选大的
        int no = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);
        //返回当前结点偷和不偷
        return new int[]{yes,no};
    }
}

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

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

相关文章

告别信息搜寻烦恼:用fastgpt快速部署国内大模型知识库助手

Docker Compose 快速部署 使用 Docker Compose 快速部署 FastGPT 推荐配置 环境最低配置(单节点)推荐配置测试2c2g2c4g100w 组向量4c8g 50GB4c16g 50GB500w 组向量8c32g16c64g 200GB 部署架构图 1. 准备好代理环境(国外服务器可忽略&…

web游戏-飞机大战

H5小游戏源码、JS开发网页小游戏开源源码大合集。无需运行环境,解压后浏览器直接打开。有需要的订阅后,私信本人,发源码,含60小游戏源码。如五子棋、象棋、植物大战僵尸、贪吃蛇、飞机大战、坦克大战、开心消消乐、扑鱼达人、扫雷…

STM32自学☞I2C

这里只是大体介绍,具体的可参考STM32数据手册

Python算法100例-3.2 水仙花数

完整源代码项目地址,关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.问题拓展7.巧用字符串技巧 1.问题描述 输出所有的“水仙花数”。所谓的“水仙花数”是指一个三位数,其各位数字的立方和等于该…

[C语言]——C语言常见概念(3)

目录 一.字符和ASCII编码 二.字符串和\0 三.转义字符 四.语句和语句分类 1.空语句 2.表达式语句 3.函数调用语句 4.复合语句 5.控制语句 五.注释 1.注释的2种形式 1.1 /**/ 的形式 1.2 // 的形式 2.注释会被替换 一.字符和ASCII编码 在键盘上可以敲出各种字符&am…

【UE Niagara】纳米蠕虫效果

效果 步骤 1. 新建一个Niagara系统,选择一个空模板,这里命名为“NS_Worm” 打开“NS_Worm”,重命名发射器为“Leader” 先添加“Spawn Burst Instantaneous”模块来单次生成粒子 为了让粒子持续停留在关卡中,需要在“Particle St…

MybatisPlus的使用(一)--基本配置与无条件查询

创建测试用的数据库 CREATE DATABASE mybatis_plus /*!40100 DEFAULT CHARACTER SET utf8mb4 */; use mybatis_plus; CREATE TABLE user ( id bigint(20) NOT NULL COMMENT 主键ID, name varchar(30) DEFAULT NULL COMMENT 姓名 , age int(11) DEFAULT NULL COMMENT 年龄 , em…

JavaWeb - 1 - 概述

一.什么是Web? Web:全球广域网,也称为万维网(www World Wide Web),能够通过浏览器访问的网站 二.Web网站的工作流程 三.Web网站的开发模式 3.1 前后端分离开发(主流) 3.2 混合开发…

thymeleaf 一个莫名其妙的错误提示 org.attoparser.ParseException

thymeleaf 一个莫名其妙的错误提示 介绍 开发过程中遇到一个莫名奇妙的错误,一时竟然不知道怎么解决,找官网也没有找到 问题 页面显示 错误日志 org.attoparser.ParseException: (Line 96, Column 5) Malformed markup: Attribute “}” appears m…

羊大师揭秘羊奶将成为,健康新选择

羊大师揭秘羊奶将成为,健康新选择 羊奶作为一种传统的营养食品,已经在全球范围内受到了广泛的关注和认可。随着人们对健康生活的追求和对食品安全的重视,羊奶正逐渐成为健康的新选择。 羊奶的营养价值得到了科学的验证。羊奶中含有丰富的蛋…

【深度学习笔记】5_5 LeNet

注:本文为《动手学深度学习》开源内容,部分标注了个人理解,仅为个人学习记录,无抄袭搬运意图 5.5 卷积神经网络(LeNet) 在3.9节(多层感知机的从零开始实现)里我们构造了一个含单隐藏…

飞书文档批量导出

背景需求 最近所参与的项目即将结项,需要将飞书中的产品需求文档(PRD)交付给甲方,由于文档较多,大概有两百多个,一个一个的下载导出,太麻烦了(PS:本人比较懒)…

ruoyi-nbcio-plus的Vue3前端升级组件后出现的问题(一)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址: http://122.227.135.243:9666 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbach…

Jenkins 安装

目录 1、部署 Jenkins 安装配置 Jenkins 解锁 Jenkins 安装 Jenkins 插件 创建管理员账号 手动安装插件 2、Jenkins 从 GitLat 拉取代码 安装 Jenkins 插件 在 node-16 上生成密钥对 把公钥配置到 gitlab 上 把 root 用户私钥配置到 jenkins 上 Jenkins 创建一个任务…

PCSA时钟控制集成之时钟门控集成

1.4 时钟门控集成 高级时钟门控是使用每个时钟域的时钟控制器组件实现的。时钟控制器支持多个组件的时钟门控,并为每个组件提供一个Q-Channel接口。 大多数Arm组件都支持这种类型的时钟门控。大多数组件使用Q-Channel。一些较早的组件使用AXI LPI,但在…

2024全国护网行动HW行动招聘/收人!!!

2024全国护网行动HW行动招聘 溯蓉信创开始收人啦!!!现在开始收录2024HW简历,感兴趣的小伙伴扫码二维码添加微信 我们签约后,入场即预付款3k,签约后我们会在HW之前对我们的人员进行HW培训,保证上…

AI加速引擎PAI-TorchAcc:整体介绍与性能概述

作者:沈雯婷、黄奕桐、艾宝乐、王昂、李永 1、简介 PAI-TorchAcc(Torch Accelerator)是阿里云人工智能平台开发的Pytorch上的大模型训练加速框架。 PAI-TorchAcc提供了一套基于Pytorch的简洁、易用的接口,无需进行模型转换就可以无缝地接入HuggingFac…

HTTP笔记(五)

个人学习笔记(整理不易,有帮助点个赞) 笔记目录:学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 目录 一:HTTP报文首部 (1)HTTP请求报文 (2&#xff09…

【C++庖丁解牛】默认成员函数

📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 目录 前言1. 构造函数1.1 …

Linux配置网卡功能

提示:工具下载链接在文章最后 目录 一.network功能介绍二.配置network功能2.1 network_ip配置检查 2.2 network_br配置2.2.1 配置的网桥原先不存在检查2.2.2 配置的网桥已存在-修改网桥IP检查2.2.3 配置的网桥已存在-只添加网卡到网桥里检查 2.3 network_bond配置检查 2.4 netw…