leetcode124. 二叉树中的最大路径和
二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 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
算法思想
首先我们确认一点,如果一个路径是有效的,那么选择了他的父节点之后,他的两个子节点最多只能选择一个。
所以如果我们算当前节点的最大路径(即最后的结果),我们可以算自己+左子树+右子树,即是2 -> 1 -> 3 这种情况
但如果我们算的是当前节点作为子节点的贡献值的时候,就不能算自己+左子树+右子树这种情况,因为既然当前节点作为了自己点,那么就一定会有父亲节点。
当前节点的最大路径: max(自己,自己+左子树,自己+右子树,自己+左子树+右子树)
当前节点作为子节点时的贡献:max(自己,自己+左子树,自己+右子树)
搞清这一点之后,代码不算难写。
算法步骤
1.初始化:设置一个全局变量 maxSum 来存储到目前为止找到的最大路径和,初始值设为 INT_MIN。
2.递归函数 maxGain:
如果当前节点为空,返回0。 递归计算当前节点的左右子节点的最大贡献值,并且只有当这个值大于0时才考虑。
计算通过当前节点的最大路径和,即当前节点的值加上左右子节点的最大贡献值。 更新全局变量 maxSum,如果当前路径和大于maxSum,则更新 maxSum。
3.返回最大贡献值:在递归返回时,返回当前节点的值加上左右子节点中较大的贡献值,这代表了当前节点对子树的最大贡献。
4.主函数 maxPathSum:
调用 maxGain 函数,传入根节点。
返回 maxSum,即整个二叉树中的最大路径和。
具体代码
class Solution {
private:
int maxSum = INT_MIN;
public:
int maxGain(TreeNode* node) {
if (node == nullptr) {
return 0;
}
// 递归计算左右子节点的最大贡献值
// 只有在最大贡献值大于 0 时,才会选取对应子节点
int leftGain = max(maxGain(node->left), 0);
int rightGain = max(maxGain(node->right), 0);
// 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
int priceNewpath = node->val + leftGain + rightGain;
// 更新答案
maxSum = max(maxSum, priceNewpath);
// 返回节点的最大贡献值
return node->val + max(leftGain, rightGain);
}
int maxPathSum(TreeNode* root) {
maxGain(root);
return maxSum;
}
};
和此题类似的还有一些,做完此题后可以去看看。
leetcode112 | 路径总和 |
---|---|
leetcode113 | 路径总和II |
我写有详细题解,可以去看看。