精读《算法题 - 二叉树中的最大路径和》

今天我们看一道 leetcode hard 难度题目:二叉树中的最大路径和。

题目

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例1:

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

思考

第一想法是,这道题不安常理出牌,因为路径竟然不是自上而下的,而是可以横向蛇形游走的,如下图:

e1f17629e100310a9dee7cbbab975e03.png

尝试动态规划

第二想法是,这种蛇形游走的路径,求路径最大值应该用什么方法?大概率是暴力解法,因为 必须遍历完所有节点,才知道是否有更大的值的可能性,而应对暴力解法最好的策略是动态规划,那么应该如何定义状态?经过一番思考,二叉树点到点之间仅有唯一一条路径,如果我们能枚举计算经过每个点的所有可能路径的最大值,那么找到其中最大的就可以得到答案。但可惜的是,以 “点” 为变量没办法写转移方程。

以暴力解法为基础思考

此时要切换想法,经过一些思考,我决定以正序角度模拟一下寻找最大路径和的思路:首先选择一个起点,找到以该起点开始的最大路径合。那么从该起点就有最多 3 种走法,分别是向根节点走、左子节点、右子节点走:

2cbe8500fde5cb4e97f8dae6ea8c712c.png

最暴力的解法是遍历每个点,把所有方向都走一遍,找到所有可能的最大值。 这无疑是一个最有效的兜底解法,但效率太低,那么为了提升效率,假设一条路径的最大潜力已经计算过一次了,那么一条新路径经过时,就没必要重新算一遍。所以我们要寻找每个方向的最大贡献

寻找每个方向的最大贡献

假设我们提前找到了经过每个点的最大贡献如下:

dcc6354eb3a803f7f584d05a7869b01e.png

根节点的最大贡献 10 的含义为:从 3 向根节点走,所有可能路径能带来的最大正数收益为 10。所以此时最大路径和显然为:5 + 3 + 10 = 18.

但此时矛盾来了,根节点的最大贡献 10 是从 3 向根节点走的角度定义的,它有两个致命问题:

  1. 每个节点的最大贡献最好只能有一个数字,依赖方向的话复杂度太高了。

  2. 如果要依赖方向,那么从根节点右子节点走向根节点的最大贡献,其实依赖从左子结点出发的最大贡献,相互死锁了。

这种最大贡献几乎不可能找到,再花时间思考只是浪费时间,所以我们要改变策略了。再想想二叉树的特征是什么,怎么样能最稳定的定义每个节点的最大贡献?很容易想到的是以树的深度来定义,即 以当前节点向子节点遍历时,能带来的最大贡献。这种最大贡献是比较容易计算的。

每个子树的最大贡献

b46decadc35a7b5f81c851afa43e192b.png

如上图所示,以 8 这个节点的子树,假设通过一系列递归找到,它能提供的最大贡献就是 8,且这个贡献必须是一条没有分叉的线,这样这个最大贡献对于它的父节点才有意义,即父节点可以把这个节点连上,形成一条更长的没有分叉的线。如果子线都有分叉,整条线就会存在分叉,就不符合题意了。

这个 8 很容易计算,从叶子结点向上推,找到最大且大于 0 的子节点连成线即可。

但回到这道题,如果我们仅仅计算了每个点所在子树的最大贡献,那么其最大值仅是垂直的线中的最大值,没有考虑到该题路径可以横向蛇形游走的特性:

8cda1d92a8b258f903d7254f217429fd.png

如上图所示,红色的数字为以该点开始的子树的最大贡献,那么根节点 32 其实就是红色路径提供的路径和,对于纵向走位来说是最大的,但并不是本题最大的。本题最大的值,还得把下图红色的路径考虑上,变成一个横向的线,此时最大值达到了 32 + 8 = 40:

aca86ba40188adacd7cf3f8fc4223679.png

但其实要把线变成横向的,也仅需要多考虑另一个子节点而已,因为所有子树的最大贡献已经提前算好,根本无需再深入子子节点。也就是说,在计算最大路径和时(重要内容字体加粗!):

  1. 经过该点的最大路径和,要同时考虑该点 + 左右子树最大贡献,也就是此时路径会形成类似倒扣的 U 型。

  2. 但该节点的最大贡献呢,只能考虑该点 + 左 or 右子树最大贡献的,不能形成倒扣的 U 型,因为这个最大贡献需要被其父节点作第 1 条规则时考虑,如果此时已经是倒扣 U 型了,那么父节点再分叉一次倒扣的 U 型,就不是一条线了,可能会形成如下图所示奇怪的形状:

e4c6dccb2a2e424dd42f420c63bfc48c.png

这就是本题最精彩的思考点。

代码实现

想通了之后,代码就很简单了:

function maxPathSum(root: TreeNode | null): number {let maxValue = -Infinityfunction maxOneLinePathByNode(node: TreeNode): number {// 如果节点为空,返回负无穷,必然不会被最大路径和带上if (node === null) return -Infinity// 左子树最大贡献(如果为负数则为 0,表示不带上左子树)const leftChildMaxValue = Math.max(maxOneLinePathByNode(node.left), 0)// 右子树最大贡献 - 同理const rightChildMaxValue = Math.max(maxOneLinePathByNode(node.right), 0)// 经过该点的最大路径和const currentPointMaxValue = node.val + leftChildMaxValue + rightChildMaxValue// 刷新 maxValuemaxValue = Math.max(maxValue, currentPointMaxValue)// 返回不分叉的子树最大贡献return node.val + Math.max(leftChildMaxValue, rightChildMaxValue)}maxOneLinePathByNode(root)return maxValue
};

因为从根节点开始递归,可以算出所有子树的最大贡献,把经过每一个点的路径都考虑到了,所以答案是不重不漏的。

总结

该题有两个难点:

  1. 找到子树最大贡献思考方向。

  2. 子树最大贡献与最大路径和的计算方式稍有不同,需要分别处理。

最后,在从根节点递归寻找子树最大贡献时,就可以顺便计算出最大路径和,一定程度上是 “目标的副产物”,甚至可以怀疑该题是在思考子树最大贡献时,逆向推导出来的副产物。另一方面,也说明了子树最大贡献的重要性,它的一个衍生计算就可以是一道 hard 题。

讨论地址是:精读《算法 - 二叉树中的最大路径和》· Issue #504 · dt-fe/weekly

如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。

版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)

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

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

相关文章

随时随地时时刻刻使用GPT类应用

疑问 很多人说GPT的广泛使用可能会使人们失业,会对一些互联网公司的存活造成挑战,那么这个说法是真的吗? 这个说法并不完全准确。虽然GPT等AI技术的广泛应用可能会对某些行业和职业产生影响,但并不意味着它会导致人们失业或互联网…

群晖7.2版本安装Jellyfin

一、添加三方套件库 打开桌面【套件中心】,点击右上角的【设置】-【套件来源】-【新增】,添加矿神库 名称:我不是矿神 位置:https://spk7.imnks.com/ 二、安装Jellyfin 【套件中心】-搜索【Jellyfin】-【安装套件】 集显版群…

【MySQL--->索引】

文章目录 [TOC](文章目录) 一、索引概念二、B树与B树1.B树的特点:2.B树的特点:3.为什么使用B树而不使用B树 三、聚簇索引和非聚簇索引四、索引操作1.创建索引2. 删除索引3.全文索引 一、索引概念 mysql的查询的过程是从文件中提取到内存中查询,MySQL启动时会在内存中维护一个b…

LED点阵显示原理(取字模软件+Keil+Proteus)

前言 写这个的时候我还是有点生气的,因为发现完全按照书上面的步骤来,结果发现不理想,后面还是自己调试才解决了。-_-说多了都是泪,直接进入正文。 软件的操作还是参考我之前的博客。 LED数码管的静态显示与动态显示&#xff0…

LabelImg使用笔记

LabelImg使用笔记 文章目录 LabelImg使用笔记一、LabelImg简介1.1、特性1.2、LabelImg的热键 二、LabelImg安装三、3种格式的使用3.1、VOC格式标注3.2、yolo格式标注3.3、json格式 四、LabelMe 和 LabelImg适用场景 一、LabelImg简介 LabelImg 是一个用于图像标注的开源工具&a…

win11下使用VMmare设置CentOS7里面的静态IP

1,win11上的VMware 8 设置 2,选择VMmare上的虚拟网络编辑进行设置 #3,接下来进入虚拟机设置(就是进入CentOS7 打开终端 右键 Open Terminal ) # 切换root su root #ksana #编辑网络配置文件 vi /etc/sysconfig/networ…

【MongoDB】索引 - 单字段索引

MongoDB支持在集合文档中的任意字段上创建索引,默认情况下所有的集合都有一个_id字段的索引,用户和应用可以新增索引用于查询和操作。 一、准备工作 这里准备一些学生数据 db.students.insertMany([{ _id: 1, name: "张三", age: 20, clas…

马斯克发布大模型Grok;主流AI创意生成工具图谱;Runway视频大赛获奖作品解析;DALL-E 3图像混合操作;42章经播客推荐 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 👀 马斯克「xAI」发布首个AI大模型「Grok」 https://grok.x.ai 11月5日,马斯克旗下人工智能公司 xAI 发布了首款 AI 聊天产品…

Capto2024专为Mac电脑设计的屏幕录制和视频编辑软件

不得不说视频编辑功能:Capto提供了多种视频编辑功能,例如剪辑、旋转、裁剪、调整音频和视频的音量、加入水印、添加注释等,你能够使用Capto编辑你的视频,使之更加专业和生动。有目共睹的是录制完成后,你能够使用Capto提…

20.7 OpenSSL 套接字SSL加密传输

OpenSSL 中的 SSL 加密是通过 SSL/TLS 协议来实现的。SSL/TLS 是一种安全通信协议,可以保障通信双方之间的通信安全性和数据完整性。在 SSL/TLS 协议中,加密算法是其中最核心的组成部分之一,SSL可以使用各类加密算法进行密钥协商,…

web3 dapp React项目引入 antd 对 balance 用户token信息组件进行样式改造

好 上文 web3 React dapp中编写balance组件从redux取出并展示用户资产 我们简单处理了用户资产的展示 那么 我们继续 先启动 ganache 环境 终端输入 ganache -d然后 打开我们的项目 将合约发布到区块链上 truffle migrate --reset然后 我们启动项目 确认一切正常 还原到上文…

k8s中实现mysql主备

文章目录 一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.1 安装nfs1.2.2 部署nfs-provisioner 1.3 安装mysql1.4 备库上查看是否同步 一、k8s中实现mysql主备 1.1 环境信息 机器操作系统ipmysql版本k8s版本storageClassmaster1CentOS7.8192.168.0.20mysql5.…

C++ 代码实例:多项式除法简单计算工具

文章目录 前言代码仓库代码说明核心片段 结果总结参考资料作者的话 前言 C 代码实例:多项式除法简单计算工具。 代码仓库 yezhening/Programming-examples: 编程实例 (github.com)Programming-examples: 编程实例 (gitee.com) 代码 说明 由于代码篇幅较多&#…

【蓝桥杯省赛真题41】Scratch电脑开关机 蓝桥杯少儿编程scratch图形化编程 蓝桥杯省赛真题讲解

目录 scratch电脑开关机 一、题目要求 编程实现 二、案例分析 1、角色分析

【数据开发】大数据平台架构,Hive / THive介绍

1、大数据引擎 大数据引擎是用于处理大规模数据的软件系统, 常用的大数据引擎包括Hadoop、Spark、Hive、Pig、Flink、Storm等。 其中,Hive是一种基于Hadoop的数据仓库工具,可以将结构化的数据映射到Hadoop的分布式文件系统上,并提…

家用电脑做服务器,本地服务器搭建,公网IP申请,路由器改桥接模式,拨号上网

先浇一盆冷水! 我不知道其他运营商是什么情况。联通的运营商公网IP端口 80、8080、443 都会被屏蔽掉,想要开放必须企业备案(个人不行)才可以。也就是说,只能通过其他端口进行showtime了。 需要哪些东西? 申…

MySQL中的刷脏机制详解

名词解释 脏页:当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。 干净页:内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”。 LSN:称为日志的逻辑序列号(l…

HTB——introduction to active directory

文章目录 一、Active directory structure二、Active Directory Terminology 一、Active directory structure Active Directory (AD) 是用于 Windows 网络环境的目录服务。它是一种分布式分层结构,允许集中管理组织的资源,包括用…

MIPI-CSI-2 RAW10笔记

好文: 【精选】摄像头的MIPI接口、DVP接口和CSI接口-CSDN博客【精选】摄像头的MIPI接口、DVP接口和CSI接口-CSDN博客 (56 封私信 / 24 条消息) 显示器的 VGA、HDMI、DVI 和 DisplayPort 接口有什么区别? - 知乎 (zhihu.com) 嵌入式工程师必备&#x…

基于白鲸算法的无人机航迹规划-附代码

基于白鲸算法的无人机航迹规划 文章目录 基于白鲸算法的无人机航迹规划1.白鲸搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要:本文主要介绍利用白鲸算法来优化无人机航迹规划。 1.白鲸搜索算法 …