Leetcode124-二叉树中的最大路径和

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其 最大路径和 。

在这里插入图片描述
在这里插入图片描述

题解

思想:

题解转载自xiao_ben_zhu
路径每到一个节点,有 3 种选择:1. 停在当前节点。2. 走到左子节点。3. 走到右子节点。
走到子节点,又面临这 3 种选择,递归处理就好。
注意,不能走进一个分支又掉头回来走另一个分支,路径重叠,不符合定义。
在这里插入图片描述
定义递归函数
我们关心路径走入一个子树,能从中捞取的最大收益,不用管具体怎么走。
定义dfs函数:返回当前子树能向父节点“提供”的最大路径和。 分为三种情况:

  • 路径停在当前子树的根节点,收益:root.val
  • 走入左子树,最大收益:root.val + dfs(root.left)
  • 走入右子树,最大收益:root.val + dfs(root.right)
    这对应了前面讲的三种选择,最大收益取三者中的最大值。

再次提醒: 一条从父节点延伸下来的路径,不能走入左子树又掉头走右子树,不能两头收益。
当遍历到null节点时,返回 0,收益为 0。
如果子树 dfs 结果为负,走入它,收益不增反减,该子树应被忽略,让它返回 0,如同砍掉。
在这里插入图片描述
子树中的内部路径要包含根节点
题目说,路径不一定经过根节点,说明,最大路径和可能产生于局部子树中,如下图左一。
因此每递归一个子树,都求当前子树内部的最大路径和,下图右一,比较出最大的。
注意: 一个子树内部的路径,要包含当前子树的根节点。如果不包含,那还算什么属于当前子树的路径,而是当前子树的子树的内部路径。
所以,一**个子树内部的最大路径和 = 左子树提供的最大路径和 + 根节点值 + 右子树提供的最大路径和。**即 dfs(root.left) + root.val + dfs(root.right)
在这里插入图片描述

代码实现

注意区分当前子树的内部最大路径和(dfs(root.left)+dfs(root.right)+root.val) 和 当前子树对外所能贡献的最大路径和(root.val+Math.max(leftMax,rightMax),因为要对外走所,不能反复经过root,所以只能取左右子树路径值中的较大值)

class Solution {
    int res = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        dfs(root);
        return res;
    }

    public int dfs(TreeNode root){
        //递归终止条件:node==null
        if(root==null){
            return 0;
        }
        
        //左子树所能提供的最大值
        int leftMax=Math.max(dfs(root.left),0);
        int rightMax=Math.max(dfs(root.right),0);
        //总的最大路径和=当前子树的内部最大路径和 和 原先记录的最大路径值中较大的那一个
        res = Math.max(res,leftMax+rightMax+root.val);
        //返回对外所能贡献的路径之和:因为不可走重复节点,所以只能取左右子树中路径值贡献更大的那一条
        return root.val+Math.max(leftMax,rightMax);
    }
}

在这里插入图片描述

复盘总结
递归一个树,会对每个子树做同样的事(你写的处理逻辑)。
通过求出每个子树对外提供的最大路径和,从底而上,求出每个子树内部的最大路径和,后者的求解要用到前者,明白二者的关系。
每个子树的内部最大路径和,都挑战一下最大纪录,递归结束时,最大纪录就有了。
思考递归问题,不要纠结细节实现,思考方式是自顶而下、屏蔽细节的,随着递归出栈,子问题自下而上地解决,最后解决了整个问题,内部细节是子递归实现的。
画出递归树对于递归问题的解决蛮有用,辅助理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值