leetcode 337. 打家劫舍 III-[python3图解]-递归+记忆化搜索

news2024/11/26 14:54:32

题目

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为root。除了root之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。给定二叉树的root。返回在不触动警报的情况下,小偷能够盗取的最高金额。

示例

在这里插入图片描述

  • 输入: root = [3,2,3,null,3,null,1]
  • 输出: 7
  • 解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7

题解

题目很好理解,小偷也需要会二叉树,不然容易出发报警。题目的意思是其实很简单,就是小偷第不能在父子节点同时打劫。以示例中的例子来进行说明。
第一步是对根节点的判断,根节点有两种选择一种是打劫,一种是不打劫。
在这里插入图片描述

至于是打劫还是不打劫,需要根据后续的子树进行判断。如果根节点选择打劫的话那么根节点的子节点2与3均不能打劫,这种情况下整个树的能打劫的最多金额就从根节点转移到了左右子树。根节点能打劫这种情况的获得最高金额就可以写成:根节点的值3+左子树获得的最高金额+右子树获得的最高金额。这里左右子树的根节点均不可打劫。可见需要分两种情况对子树进行处理。这里明显也是一个递归过程。
这里为了好理解假设f(node)表示针对以node为根节点的子树打劫其根节点的情况下整个子树能获得的最高金额。p(node)表示针对以node为根节点的子树不打劫其根节点的情况下整个子树能获得的最高金额。我们可以写出其递归方程如下:
f(node)=node.value+f(node.left)+f(node.right)
p(node)的情况要稍微复杂一些,因为node没选,所有其左右子树有两种情况,即可选可不选。那么我们如何来判断是两个子树的根节点选还是不选。
在这里插入图片描述

比如上图所示的如何判断[2,3]这刻子树是的根节点2是选还是不选呢。只需要计算[2,3]这根子树两种情况的打劫金额即可,max(f([2,3],p([2,3])))。那么p(node)的递归方程可以写成如下形式:
p(node)=max(f(node.left),p(node.left))+max(f(node.right),p(node.right))
那么接下来我们可以写递归函数了。这里写下我们思路,由于需要区分根节点选与不选,我这里很直接,参数加一个select,select为1的表示打劫根节点。
那么代码写成如下形式:

class Solution:
    def rob(self, root: Optional[TreeNode]) -> int:
        @cache
        def dfs(select,curr_node):
            #终止条件,节点不存在终止
            if not curr_node:
                return 0
            #选择当前子树根节点
            if select==1:
                #f(node)的方程式
                return curr_node.val+dfs(0,curr_node.left)+dfs(0,curr_node.right)
            else:
                #p(node)的方程式
                return max(dfs(0,curr_node.left),dfs(1,curr_node.left))+max(dfs(0,curr_node.right),dfs(1,curr_node.right))
        return max(dfs(1,root),dfs(0,root))

这个代码不加装饰器@cache会超时,显然存在大量的重复计算需要利用记忆化搜索方法提高效率。

这个代码也可以稍微修改成官方代码的形式,即递归函数是一个输入,不需要加select区分,把两种情况的结果均返回。

class Solution:
    def rob(self, root: Optional[TreeNode]) -> int:
        @cache
        def dfs(curr_node):
            #终止条件,节点不存在终止
            if not curr_node:
                return [0,0]#第一个表示选根节点情况,第二个返回提是不选根节点的情况
            left=dfs(curr_node.left)
            right=dfs(curr_node.right)
            #递归方程
            return [curr_node.val+left[1]+right[1],max(left)+max(right)]
        return max(dfs(root))

这两种计算复性上没有区别。

计算复杂度

时间复杂度 O ( n ) O(n) O(n),因为这里只对整个树的所有节点遍历一次,n表示树中节点个数。
空间复杂度 O ( n ) O(n) O(n),空间复杂度跟哈希表空间有关,这里递归hash表的空间代价为 O ( n ) O(n) O(n)

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

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

相关文章

【Python百日进阶-数据分析】Day130 - plotly柱状图(条形图):go.bar()实例1

文章目录4.2 plotly.graph_objects条形图4.2.1 go的基本条形图4.2.2 分组条形图4.2.3 堆叠条形图4.2.4 带悬停文本的条形图4.2.5 带直接文本标签的条形图4.2.6 使用uniformtext控制文本大小4.2.7 旋转条形图标签4.2.8 自定义单个条颜色4.2.9 自定义单个条的宽度4.2.10 自定义单…

NetInside网络分析为企业IT工作保驾护航(二)

前言 某企业的DMS经销商在线系统,最近一段时间运维人员经常接到反馈,DMS使用出现大量访问慢的情况,针对此情况进行监测分析。 该企业已部署NetInside流量分析系统,使用流量分析系统提供实时和历史原始流量,重点针对DMS系统性能进…

MobileNetV3基于NNI剪枝操作

NNI剪枝入门可参考:nni模型剪枝_benben044的博客-CSDN博客_nni 模型剪枝 1、背景 本文的剪枝操作针对CenterNet算法的BackBone,即MobileNetV3算法。 该Backbone最后的输出格式如下: 假如out model(x),则x[-1][hm]可获得heatma…

Spring框架04(Spring框架中AOP)

一、spring中bean的生命周期 1.singleton 容器启动的时候创建对象,容器正常关闭时销毁对象 2.prototype 获取对象的时候创建对象,spring容器不负责对象的销毁 生命周期的过程: 1.调用无参创建对象 2.调用set方法初始化属性 3.调用初始化…

知识付费系统源码,可直接打包成app、H5、小程序

知识付费,在近几年来,越来越受到大家的关注。知识付费系统源码是将知识通过互联网渠道变现的方式。以知识为载体,通过付费获得在线知识以及在线学习所带来的收益。知识付费平台主要以分享知识内容,内容分为直播、录播、图文等形式…

【从零开始学爬虫】采集收视率排行数据

l 采集网站 ​【场景描述】采集收视率排行数据。 【源网站介绍】收视率排行网提供收视率排行,收视率查询,电视剧收视率,综艺节目收视率和电视台收视率信息。 【使用工具】前嗅ForeSpider数据采集系统 【入口网址】http://www.tvtv.hk/archives/category/tv 【采集内容】 …

产线工控安全

场景描述 互联网飞速发展,工业4.0的大力推行,让工控产线更加智能化,生产网已经发展成一个组网的计算机环境。这些工控产线组网中的所有工控设备现在统称为主机。 信息化虽然提高各大企业的生产效率,但也会遭遇各类安全问题&…

Problem B: 算法10-15~10-17:基数排序

Problem Description 基数排序是一种并不基于关键字间比较和移动操作的排序算法。基数排序是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法。 通过对每一个关键字分别依次进行排序,可以令整个关键字序列得到完整的排序。而采用静态链表存储记录&#xf…

FAST-LIO论文阅读

1. 摘要 本文提出一个开销较小且鲁棒的激光惯性里程计框架。使用迭代扩展卡尔曼滤波器来实现激光雷达特征点和IMU的紧耦合,可以在快速运动、有噪声或重复纹理等退化环境中鲁棒地定位。为了在测量数据量很大的情况下降低开销,提出了计算卡尔曼增益的新公…

如何做电商运营

电商是通过电子设备和网络技术进行的商业模式,通俗的来说也就是通过网络结识买家完成最终交易。电子商务凭借它便宜,丰富和方便的特性,迅速占领了中国一大半的经济市场,作为个人怎么才能做好电商呢?掌握这几个要点就不…

物联网开发笔记(63)- 使用Micropython开发ESP32开发板之控制ILI9341 3.2寸TFT-LCD触摸屏进行LVGL图形化编程:显示中文

一、目的 这一节我们学习如何使用我们的ESP32开发板来控制ILI9341 3.2寸TFT-LCD触摸屏进行LVGL图形化编程的第一步:显示中文。 二、环境 ESP32 3.2寸 ILI9341触摸屏 Thonny IDE 几根杜邦线 Win10 接线方法:请看上一篇文章。 三、流程介绍 …

Verilog刷题HDLBits——Conwaylife

Verilog刷题HDLBits——Conwaylife题目描述代码结果题目描述 Conway’s Game of Life is a two-dimensional cellular automaton. The “game” is played on a two-dimensional grid of cells, where each cell is either 1 (alive) or 0 (dead). At each time step, each c…

【图像融合】小波变换(加权平均法+局域能量+区域方差匹配)图像融合【含Matlab源码 1819期】

⛄一、小波变换彩色图像融合简介 1 前言 图像融合是将不同传感器所获得的多个图像根据某种算法进行融合处理,取长补短,使一幅图像能够更清楚、更准确地反映多幅图像的信息,多聚焦彩色图像融合是图像融合的一个分支。目前在各种图像采集与分析系统中已使用的CCD数码相机,对于聚…

分享7 个VUE项目用得上的JavaScript库

借助开源库加速VUE项目的开发进度是现代前端开发比较常见的方式,平常收集一些JavaScript库介绍,在遇到需要的时候可以信手拈来。 VUE 生态有很多不错的依赖库或者组件,是使用VUE开发前端的原因之一。 1. vueuse 这是 GitHub 上星最多的库之…

【coarse-to-fine:基于频谱和空间损失约束】

UPanGAN: Unsupervised pansharpening based on the spectral and spatial loss constrained Generative Adversarial Network (UPanGAN:基于频谱和空间损失约束的生成式对抗网络的无监督全色锐化) 研究发现,在大多数基于神经网…

扎根底层核心技术:OPPO发布旗舰蓝牙音频SoC芯片

OPPO自研芯片能力更进一步。 2022年12月14日,OPPO发布自研芯片马里亚纳MariSilicon Y,作为一颗旗舰蓝牙音频SoC,实现了三大核心技术突破,使OPPO具备了计算连接能力的蓝牙SoC平台的设计能力。 这是OPPO发布的第二款自研芯片。去年…

初学者数据分析——Python职位全链路分析

最近在做Python职位分析的项目,做这件事的背景是因为接触Python这么久,还没有对Python职位有一个全貌的了解。所以想通过本次分析了解Python相关的职位有哪些、在不同城市的需求量有何差异、薪资怎么样以及对工作经验有什么要求等等。分析的链路包括&…

用了那么久的Vue,你了解Vue的报错机制吗?

Vue的5种处理Vue异常的方法 相信大家对Vue都不陌生。在使用Vue的时候也会遇到报错,也会使用浏览器的F12 来查看报错信息。但是你知道Vue是如何进行异常抛出的吗?vue 是如何处理异常的呢?接下来和大家介绍介绍,Vue是如何处理这几种…

【数据结构】树以及二叉树的概念

作者:一个喜欢猫咪的的程序员 专栏:《数据结构》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》 目录 树的概念: 树的相关概念: 树如何表示&#xff…

Anaconda中Python虚拟环境的创建、使用与删除

本文介绍在Anaconda环境下,创建、使用与删除Python虚拟环境的方法。 在Python的使用过程中,我们常常由于不同Python版本以及不同第三方库版本的支持情况与相互之间的冲突情况,而需要创建不同的Python虚拟环境;在Anaconda的帮助下&…