题目
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 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
思路
这道题我们可以采用递归的方式来求解。对于每一个节点,我们可以计算其左子树的最大贡献值和右子树的最大贡献值,然后计算以当前节点为根节点的最大路径和。这个过程可以用一个递归函数来实现,递归函数的返回值表示以当前节点为根节点的最大路径和。最终的答案就是递归函数的返回值和一个全局变量的最大值之间的较大值。 具体来说,我们可以定义一个递归函数dfs(node),表示以node为根节点的最大路径和,函数返回值为一个整数。对于每个节点,我们可以计算出左子树的最大贡献值和右子树的最大贡献值,然后计算以当前节点为根节点的最大路径和。当我们计算以当前节点为根节点的最大路径和时,我们可以分为两种情况,分别是以当前节点为起点的最大路径和,以及左右子树的最大路径和加上当前节点的值。这两种情况的最大值即为以当前节点为根节点的最大路径和。最后我们需要更新全局最大值。
- 时间复杂度为O(n)
- 空间复杂度为O(log(n))
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/
function maxPathSum(root: TreeNode | null): number {
let res = Number.MIN_SAFE_INTEGER;
// 递归求子树的最大值
const dfs = (root) => {
if(!root) return 0;
const left = Math.max(0, dfs(root.left));// 左侧最大值,不能是负数
const right = Math.max(0, dfs(root.right));
res = Math.max(res, left + right + root.val);// 左 + 右 + 跟组成的完整路径和
return root.val + Math.max(left, right);// 左右,选一个路径
}
dfs(root);
return res;
};