目录
1 题目描述
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
示例 1:
输入: [1,2,3] 1 / \ 2 3 输出: 6
示例 2:
输入: [-10,9,20,null,null,15,7] -10 / \ 9 20 / \ 15 7 输出: 42
2 题目分析
先来看看题目,这里所求的最大路径的起点和终点并非是根结点和叶子节点,而是二叉树中任意两个节点的,那么我们来分析一下,经过任一结点的路径和可能有哪些情况呢?
①该结点本身;
②过该结点左子结点的最大路径和加上该结点;
③过该结点右子结点的最大路径和加上该结点;
④过该结点左子结点的最大路径和以及过该结点右子结点的最大路径和再加上该结点。即是横跨该结点的左右子树。
因此,假设该结点值为val,过左子结点的最大路径和为l,过右子结点的最大路径和为r,那么应该该结点的最大路径和就应当是max(val,l+val,r+val,l+r+val),即四种情况中的最大值。
那么,该怎么计算其中的l和r呢?计算l或者r,当然也是递归计算前面几种情况,即递归计算过左子结点的最大路径和以及过右子结点的最大路径和,但是这里有一点需要注意:计算过左子结点或右子结点的最大路径和时,需要排除第④种情况,因为第④种情况是横跨左右子树的,如果计算了第④种情况,那么当前结点是无法和它的左子结点或右子结点的最大路径和相连的。
举个例子,将示例二中的根结点-10换成10,其右子结点为20,按照前面的说法,过根结点10的最大路径和的一种可能就是过其右子结点的最大路径和再加上根结点10,此时如果在计算过其右子结点的最大路径和的时候计算了第④种情况,那么最大路径和最终就必然是10+15+20+7,这显然是不正确的,因为这条路径横跨了根结点10的右子结点的左右子树,是无法达到根结点的。
简单来说,如果将当前结点当做根结点,那么计算当前结点的最大路径和时就要考虑横跨当前结点左右子树的情况;如果将当前结点作为其父节点的子结点,那么计算过当前结点的最大路径和时就不能考虑横跨的情况。
3 代码实现
int maxPathSum(TreeNode* root) {
if(!root)return 0;
int m=INT_MIN; //存放最大路径和
helper(root,m); //将m传入,便于更新最大值m
return m;
}
int helper(TreeNode* root,int &m) //计算过当前结点的最大路径和
{
if(!root)return 0;
int l=helper(root->left,m); //过当前结点左子结点的最大路径和
int r=helper(root->right,m); //过当前结点右子结点的最大路径和
int curSum=max(root->val,max(l+root->val,r+root->val)); //过当前结点的最大路径和
int curMax=max(curSum,l+r+root->val); //如果将当前结点作为根结点,就要考虑横跨的情况
m=max(m,curMax); //更新最大值
return curSum; //返回过当前结点的最大路径和
}