题目
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
思路:
这种问题,肯定要先想办法把问题化小。
虽然题目说了最大路径和不一定会走根节点,但我们仍要以任意一个节点为根节点的情况去分析,这个不影响。
某个节点node的最大路径和,是该节点值node.val加上它左侧的最大路径leftBestPath和右侧的最大路径rightBestPath。
那么这里左侧的最大路径leftBestPath,是去node.left的子树里面找一条路径值最大的
我们定义一个概念,节点的最优路径值:就是某一个节点,从它开始向下找,找一条值最大的路径。
从它开始向下,无非是选择向左或者向右走,或者不走停住。
选择向哪边走,就是要比较上面说的3种情况的值,左子节点的最优路径、右子节点的有最路径、0
我们定义一个方法getBestPath去计算任意节点的最优路径值
这里就可以得到,某一个节点的最优路径值公式
解释一下就是
某节点的最优路径 = 它左子节点的最优路径、右子节点的最优路径、0,比较取最大值 getBestPath(node) = Math.max(Math.max(getBestPath(node.left),0),Math.max(getBestPath(node.right),0)) 这里因为该题有可能有负节点,所以我们需要去和0比较,如果该节点的最优路径值小于0,那么我们宁可不要了,这条路就不往下走了。如果左右都小于0,那就停在原地最划算。
接着我们要分析某个节点的最大路径和,最大路径和 == 当前节点值 + 左侧最优路径 + 右侧最优路径
这样我们仍然选择从跟节点开始遍历,采用后序遍历的方式,分别算出左右子节点的最优路径值,然后和当前节点值相加,得到的值我们用一个变量来维护MaxPathValue,我们继续往下遍历,每计算一次节点的最大路径和,都去和MaxPathValue比较一下,如果更大,则更新MaxPathValue
/**
* @param {TreeNode} root
* @return {number}
*/
var maxPathSum = function(root) {
maxPathValue = -Infinity;
getBestPath(root);
return maxPathValue;
};
function getBestPath(node){
if(!node) return 0;
let leftBestPath = Math.max(getBestPath(node.left),0);
let rightBestPath = Math.max(getBestPath(node.right),0);
let currentBestPath = node.val + leftBestPath + rightBestPath;
maxPathValue = Math.max(currentBestPath,maxPathValue)
return node.val + Math.max(leftBestPath,rightBestPath)
}
复杂度分析
时间复杂度:O(n),这里需要遍历所有的节点
空间复杂度:O(n),递归调用需要栈去额外存储函数上下文,所以这里的n就是二叉树的最大高度,最坏的情况,当二叉树是一个链表的时候,为O(n)