IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode二叉树中的最大路径和 -> 正文阅读

[数据结构与算法]LeetCode二叉树中的最大路径和

124. 二叉树中的最大路径和

路径?被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中?至多出现一次?。该路径?至少包含一个?节点,且不一定经过根节点。

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

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

示例 1

输入:root = [1,2,3]

输出:6

解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2

输入:root = [-10,9,20,null,null,15,7]

输出:42

解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

思路:

? 这道题是一个困难题。因为它确实不像传统二叉树的方法,简单写一下递归就可以得到结果。无法单单用递归解决的原因在于在一棵二叉树里画的路径可以是各种各样的——可以直接从根节点沿着一条路线画到子节点;也可以从某个子节点起,往上行走至某中间节点,再下落到另一个子节点上……可见,我们的路径可以是各种各样,尤其是题目中的节点还有负数的情况,这也让整个问题看起来十分复杂。

? 首先说明,下面的题解会写的很“勉强”(这也是我自己写的比较别扭的一篇思路了),所以千万不要钻牛角尖。我还是建议一半理解+一半记忆。

? 虽然我们可能的“最大路径”多种多样,但我们总归可以将他们分成两类:可以用递归寻找(“竖着”的路径) 以及 不可以用递归寻找(“横着”的路径)

? 对于前者,我们就照常使用我们平时解决二叉树的方法去写递归;对于后者,我们开设一个全局变量来实时更新存储。最终我们将两类的总结果进行比较,得到最大值。

? 具体来看,我们把问题缩小,一个大二叉树,我们想象成一棵棵只有根、左节点、右节点的小树。这一棵棵的小树构成大树,我们只需要考虑小树即可。按照题意:一颗三个节点的小树的结果只可能有如下6种情况:

根?+?左?+?右

根?+?左

根?+?右

要看能否进行递归寻找,就要看能否从根节点向下延伸

? 其中可以递归查找的情况有:?+??+?这三种,可以想象成拿着笔从根出发,最起码可以向左向右走或者不动,起码可以保持路径是“竖着”的。可以发现一定要包含根节点,这样我们定义递归函数的时候,就是传入一个节点,传出以传入节点为根节点的最大路径

? 而不可以递归查找的情况有:++这三种,对于只有左或者右的情况,我们都无法碰到根节点,自然无法递归延伸;对于根,左,右都存在的情况,明显是一个“横着”的路径,所以也是无法通过延伸递归来获得的。

? 好了,点到为止!就算没有完全看懂思路也没关系,我们直接看代码!很好理解和记忆:

代码:

#先把情况列到最上面作为参考

#?根?+?左?+?右

#?根?+?左

#?根?+?右

#?根

#?左

#?右

class?Solution(object):

????def?maxPathSum(self,?root):

????????no_di=[float('-inf')]#no_di存放非递归最大

????????def?di(root):#di返回以root为根节点的最大路径

????????????if?not?root:#老递归了,定义base case

????????????????return?float('-inf')?#因为节点值有负的?所以用负无穷?不能用0

????????????right?=?di(root.right)#获得以它右节点为根节点的最大路径

????????????left?=?di(root.left)#获得以它左节点为根节点的最大路径
            #左,右,根+左+右

????????????no_di[0]?=?max(no_di[0],root.val+right+left,right,left)#非递归
            #根,根+左,根+右

????????????di_=max(root.val,root.val+left,root.val+right) # di_存放递归最大

????????????return?di_

????????new_max=di(root)#不能把这个di(root)直接放到下面的return

????????#因为di函数里要修改no_di[0],所以他要先执行

????????return?max(no_di[0],new_max)

小结:

? 我们单看递归的部分(不去管no_di即非递归相关),可以发现函数di(root)的功能就是传入节点root,计算其左节点的最大路径和右节点的最大路径,然后计算max(自身值,自身值+左,自身值+右)作为di(root)的返回值。这样子就可以完美的计算出“竖直”方向上的最大路径了。

? 而“横着”的路径,则在每次递归函数中尝试与全局变量进行更新,比较巧妙地放在了递归函数里。

? 代码中要注意因为我们的节点有负数的情况,因此初始化最大值要用负无穷float(‘-inf’)而不是0。此外,存放非递归最大的变量no_di我用的一个列表来存放,这样可以充当全局变量的作用,否则在leetcode里面可能会找不到该变量,算是一个小技巧,之前也提到过。

? ……

? 2021年的最后一个小时,留个记录,祝岁月静好,国泰民安~

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-01 14:11:59  更:2022-01-01 14:12:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:24:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码