LeetCode_BinaryTree_50. Binary Tree Maximum Path Sum 二叉树中的最大路径和【递归】【Java】【困难】

本文详细解析了如何求解二叉树的最大路径和问题,通过递归策略,分别考虑左子树、根节点和右子树的最优路径,并在全局维护最大路径和。代码以Java实现,包括关键的解题思路和过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一,题目描述

英文描述

中文描述

示例与说明

二,解题思路

三,AC代码

Java

四,解题过程

第一搏

第二搏


 

一,题目描述

英文描述

A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root.

The path sum of a path is the sum of the node's values in the path.

Given the root of a binary tree, return the maximum path sum of any non-empty path.

中文描述

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例与说明

提示:

  • 树中节点数目范围是 [1, 3 * 10^4]
  • -1000 <= Node.val <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二,解题思路

最大路径只有三种情况:(其中最优路径为负时,不纳入结果计算中)

  • 左子树中最优路径 + 根节点 + 右子树中最优路径;
  • 左子树中最优路径;
  • 右子树中最优路径;

设计递归程序时,需要注意自定义方法getMaxPathSum的返回值不需要设置为最终结果(如果设置为最终结果的话,就需要在递归程序中考虑是否采取根节点、是否采取左右子树等细节,最终导致递归程序越来越复杂,没有充分利用递归简化细节的特点)

这里将getMaxPathSum的返回值定义为:root.val + max(maxLeftSum, maxRightSum),即根节点+左右子树中较大的路径和。(因为只要是一条路径,就一定包含根节点,所以返回的结果中必须要包含根节点的值,这样才不会遗漏)

需要注意一点:

  • getMaxPathSum的返回值是包含根节点的最优路径,不一定是最终的结果!!!所以需要在全局设置一个变量,用来存储遍历过程中的最终结果;

三,AC代码

Java

class Solution {
    private int ans = -1001;
    public int maxPathSum(TreeNode root) {
        getMaxPathSum(root);
        return ans;
    }
    public int getMaxPathSum(TreeNode root) {
        if (root == null) return 0;
        // 小于零表示会产生负增益,需要剔除
        int maxLeftSum = Math.max(getMaxPathSum(root.left), 0);
        int maxRightSum = Math.max(getMaxPathSum(root.right), 0);
        int tempSum = root.val + maxLeftSum + maxRightSum;
        // 在递归的过程中获得并更新最大值
        ans = Math.max(ans, tempSum);
        return root.val + Math.max(maxLeftSum, maxRightSum);
    }
}

四,解题过程

第一搏

唉,面向测试用例编程也搞不定。。。

class Solution {
    public int maxPathSum(TreeNode root) {
        int[] ans = getMaxPathSum(root, root);
        return ans[0];
    }
    public int[] getMaxPathSum(TreeNode root, TreeNode sourceRoot) {
        int[] ans = new int[2];
        ans[0] = -1001;// !!!记得初始化
        ans[1] = 0;
        if (root == null) return ans;
        
        int[] leftPathSum = getMaxPathSum(root.left, sourceRoot);
        int[] rightPathSum = getMaxPathSum(root.right, sourceRoot);

        // 根节点值大于零
        if (root.val >= 0) {
            // 左右两子树的根节点都没有被采纳
            if (leftPathSum[1] == 0 && rightPathSum[1] == 0) {
                if (root.val >= leftPathSum[0] && root.val >= rightPathSum[0]) {
                    ans[0] = root.val;
                    ans[1] = 1;// 表示将根节点纳入选择的路径中
                } else {
                    ans[0] = Math.max(leftPathSum[0], rightPathSum[0]);
                    ans[1] = 0;
                }
            }
            // 只有左子树根节点被采纳
            else if (leftPathSum[1] == 1 && rightPathSum[1] == 0) {
                // 左子树最优值+根节点值 >= 右子树最优值
                if (root.val + leftPathSum[0] >= rightPathSum[0]) {
                    ans[0] = root.val + leftPathSum[0];
                    ans[1] = 1;
                } 
                // 左子树最优值+根节点值 < 右子树最优值
                else {
                    ans[0] = rightPathSum[0];
                    ans[1] = 0;// 由于右子树根节点没有被采纳,所以这里断开了
                }
            }
            // 只有右子树根节点被采纳
            else if (rightPathSum[1] == 1 && leftPathSum[1] == 0) {
                if (root.val + rightPathSum[0] >= leftPathSum[0]) {
                    ans[0] = root.val + rightPathSum[0];
                    ans[1] = 1;
                } else {
                    ans[0] = leftPathSum[0];
                    ans[1] = 0;
                }
            }
            // 左右两子树的根节点都被采纳
            else {
                // 当root节点为为最开始树的根节点时,可以同时采纳左右两子树
                if (root == sourceRoot) {
                    ans[0] = root.val + leftPathSum[0] + rightPathSum[0];
                } 
                else {
                    ans[0] = root.val + Math.max(leftPathSum[0], rightPathSum[0]);
                }
                ans[1] = 1;
            }
        } else {
            ans[0] = Math.max(leftPathSum[0], rightPathSum[0]);
            ans[0] = Math.max(ans[0], root.val);
        }
        return ans;
    }
}

第二搏

唉,不知不觉又陷入了递归的细节中,设计递归过程切忌这一点!!!

最大路径只有三种情况:

  • 左子树中最优路径 + 根节点 + 右子树中最优路径;
  • 左子树中最优路径;
  • 右子树中最优路径;

需要注意一点:

  • getMaxPathSum的返回值是包含根节点的最优路径,不一定是最终的结果!!!所以需要在全局设置一个变量,用来存储遍历过程中的最终结果;

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值