题目2: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
提示:
- 树中节点数目范围是
[1, 3 * 104] -1000 <= Node.val <= 1000
思路分析
本题中要求的是二叉树的最大路径和,针对树中的每一个节点,经过该节点的路径有两种。
- 该节点为子节点,是构成最大路径的一段
- 该节点为根节点,其左右子树构成最大路径
该节点为子节点,是构成最大路径的一段
该节点为根节点,其左右子树构成最大路径
对每个节点计算左右子树的路径,在计算路径的过程中可以顺便计算最大路径。这样可以把该题分解为求左右子树路径问题,那么计算最大的位置应该是计算出左右子树的最大路径之后,即后序遍历的位置。
最大路径值使用一个全局变量进行记录,一个节点的最大路径值有以下几种,要从中选一个最大值记录:
- cur->val
- cur->val + left->val
- cur->val + right->val
- cur->val + left->val + right->val
当前节点作为根节点时,计算全部;当前节点作为子节点时计算前3个。
剪枝: left->val 或者right->val 为负数时,对于路径最大值是不利的,可以剪掉为负数的子节点。
针对二叉树的题目,可以有3个位置嵌入代码,这三个位置分别是前序位置、中序位置和后序位置。你可以在这3个为置嵌入巧妙的代码逻辑来完成题目的需求。 本题显然是后续位置。
有了这个遍历框架之后,你只需要考虑当前节点应该做什么即可,其它交给框架。
void traverse(TreeNode root) {
if (root == null) {
return;
}
// 前序位置
traverse(root.left);
// 中序位置
traverse(root.right);
// 后序位置
}
程序代码
//https://leetcode.cn/problems/binary-tree-maximum-path-sum/description/
//124. 二叉树中的最大路径和
#include<iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
private:
// 记录路径的最大值
int res = -0x3f3f3f3f;
public:
int getPath(TreeNode* root)
{
if(root == NULL)
{
return 0;
}
// 负数对于最大路径总和是没有正向用途的,直接剪掉
int leftv = max(getPath(root->left),0);
int rightv = max(getPath(root->right),0);
// 计算当前节点的路径总和的最大值,下面的一条语句就表达了这4种情况
// cur->val
// cur->val + left->val
// cur->val + right->val
// cur->val + left->val + right->val
int tmpres = root->val + leftv + rightv;
// 计算全局最大值
res = max(tmpres, res);
// 返回经过该节点的路径时,该节点能贡献的路径最大值,下面的一条语句就表达了这3种情况
// 1)leftv + root->val
// 2) rightv + root->val
// 3) root->val
// 从上面选择一条路
int curv = max(leftv ,rightv) + root->val;
return curv;
}
int maxPathSum(TreeNode* root) {
getPath(root);
return res;
}
};
题目感悟
- 最大路径有那几种情况
- 作为子节点,往上反馈的有哪几种情况
把这两个搞明白,递归的返回值和最大值就确定了,然后就套模板。
更多相关知识:github.com/pingguo1987…