问题描述
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
解题思路
因为是树结构,所以很容易想到要利用递归来解决。要注意的是对于每个非空真子节点而言,它要做的有两件事情:
第一,向父节点传递最大贡献值,这里的最大贡献值由两部分组成:第一部分为这个节点的val,第二部分为这个节点左子树和右子树的最大贡献值中较大的一个。
第二,维护最大路径和,当前路径和由三部分组成,当前节点val,左子树和右子树的最大贡献和。当前路径和 > 最大路径和时,进行更新。
注意
这里要注意两点:
第一,在计算左右子树的最大贡献值时要注意剪枝,如果发现其最大贡献值 < 0,则应当舍弃,此时子树的最大贡献值 = 0。
第二,注意最大路径和与最大贡献值的不同。最大路径和是当前已经扫描完毕的最大路径之和,这条路径的起点和终点一定在当前节点的子树上,计算时左右子树最大贡献值都要包含;而当前节点(设为B)最大贡献值是向上级节点(设为A)提供一种参考:A如果沿B向下延伸,是否能够获得新的最大路径和,新路径的起点一定不会是B的子树节点,因此计算时仅包含左右子树最大贡献值较大的一个。
左图已经扫描完节点2及其子树,绿色路径为当前产生最大路径和的路径,节点2向节点1上传最大贡献值时,只能选择自己的一棵子树,如右图,否则路径重叠(走完一棵子树又走另一棵)。
复杂度分析
时间复杂度:O(N),其中 N 是二叉树中的节点个数。对每个节点访问不超过 2 次。
空间复杂度:O(N),其中 N 是二叉树中的节点个数。空间复杂度主要取决于递归调用层数,最大层数等于二叉树的高度,最坏情况下,二叉树的高度等于二叉树中的节点个数。
代码
class Solution {
public:
int max_;
int maxPathSum(TreeNode* root) {
max_ = INT_MIN;
help(root);
return max_;
}
int help(TreeNode* root)
{
//节点为空,返回0
if(!root)
return 0;
//计算左右子树的最大贡献值,小于0时剪枝(舍弃)
int left = max(help(root->left), 0);
int right = max(help(root->right), 0);
//更新最大路径和
max_ = max(left+right+root->val, max_);
return root->val + max(left, right);
}
};