题目描述:
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
示例1:
示例2:
输出:48
解题思路:
在示例1中,我们感觉好像就是求子树的最大值,但从示例2中我们可以看出,当左右子树和都大于0的时候,我们只能选择左右子树中和最大的子树去组成更大的子树,于是我们形成以下思路:
- 以后序遍历整棵树
- 对于空节点,我们返回INT_MIN值
- 对于非空节点。如果其左右子树的结果都大于0,我们先要判断 左子树结果+右子树结果+root 是否为最大值,但我们只能返回选择其中一颗子树的结果(如示例2中的11只能返回7+11);如果左右子树只有一个结果大于0,我们返回 root+大于0 子树结果(都小于0则返回root),在返回前需要判断当前返回值是否为最大值
说明:以上返回值即为当前子树中包含根节点的最大路径和(因为要与其他节点连通,所以必须包含根节点),而当前子树的最大路径和(不一定包含根节点)保存在全局变量res中
代码实现:
class Solution {
public:
int res; //记录最终结果
int maxPathSum(TreeNode* root) {
if (root == nullptr)
return 0;
res = root->val;
maxPathSumCore(root);
return res;
}
//它返回在当前子树中包含root节点的情况下的最大路径和
int maxPathSumCore(TreeNode* root)
{
if (root == nullptr)
return INT_MIN;
int left = maxPathSumCore(root->left);
int right = maxPathSumCore(root->right);
int ret = root->val;
//对于中间节点,如果其左右子树和都大于0,我们只能选择一条路径作为返回值
if (left > 0 && right > 0)
{
res = max(res, root->val + left + right); //判断当前子树中是否构成最大路径和
ret += max(left, right);
}
else
{
if (left > 0) {
ret += left;
}
if (right > 0) {
ret += right;
}
if (ret > res) //判断当前子树中是否构成最大路径和
res = ret;
}
return ret;
}
};