「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」
题目介绍
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 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
提示:
- 树中节点数目范围是
[1, 3 * 10^4] -1000 <= Node.val <= 1000
解题思路
这道题目比较难理解,首先总结一下路径的几点要求:
- 任意点出发,到任意点结束
- 每个点只经过一次
- 至少包含一个节点
- 可以不经过根节点 首先我们从一个点来开始分析
以
20 这个点为例,经过 20 这个点的可以有 路径①、 路径②、 路径③,如果从 -10 这个点出发,连接 20 的话,接下去只能走 15 或者 7,不可以两个节点都走到,因为这样就会重复经过 20 这个节点了,如果从 15 出发经过 20 的话,可以走到 7 这个节点
因此,我们可以使用递归的思想,记录每个节点的左子节点的最长路径和右子节点的最大路径和,如果当前节点的父节点要走当前节点这条路径的话,那么当前节点能够提供的最大路径和就是 左子节点的最大路径和 和 右子节点的最大路径和 中较大的路径和加上当前节点的节点值,即为当前节点能够提供给父节点的最大路径和
需要注意的是,如果子节点的最大路径和小于 0 的话,如果我们走了这条路径,会导致我们的路径和变小,那么我们就不走这条路径,将子节点的路径和取 0
在遍历每个节点寻找最大路径和的过程中,我们可以定义一个变量 manSum,用于记录以当前节点为根节点的最大路径和(这里就不是当前节点的左右子节点其中一路了,而是当前节点的左右两路的最大路径和),当遍历完整棵树时,这个变量中记录的就是二叉树中的最大路径和
解题代码
var maxPathSum = function(root) {
// 记录递归过程中的最大路径和
let maxSum = Number.MIN_SAFE_INTEGER
let maxPath = root => {
// 如果当前节点为空,那么可以提供的最大路径和为 0
if (!root) return 0
// 获取左节点的最大路径和,如果小于 0 则取 0,说明不要走当前路径
const left = Math.max(maxPath(root.left), 0)
// 获取右节点的最大路径和
const right = Math.max(maxPath(root.right), 0)
// 如果以当前节点为根节点的最大路径和大于记录的值,则记录最大的路径和
maxSum = Math.max(maxSum, root.val + left + right)
// 返回当前节点能够为父节点提供的最大路径和
return root.val + Math.max(left, right)
}
maxPath(root)
return maxSum
};