精选力扣500题 第36题 LeetCode 124. 二叉树中的最大路径和【c++ / java 详细题解】

目录

      • 1、题目
      • 2、思路
      • 3、c++代码
      • 4、java代码

1、题目

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

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

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

示例 1:
精选力扣500题 第36题 LeetCode 124. 二叉树中的最大路径和【c++ / java 详细题解】_第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

2、思路

(递归,树的遍历) O ( n 2 ) O(n^2) O(n2)

在这道题目中,路径是指从树中某个节点开始,沿着树中的边走,走到某个节点为止,路过的所有节点的集合。
路径的权值和是指路径中所有节点的权值的总和。

对于一棵树,我们可以将其划分为很多的子树,如下图所示,虚线矩形围起来的子树。我们把这颗自子树的蓝色节点称为该子树最高节点。用最高节点可以将整条路径分为两部分:从该节点向左子树延伸的路径,和从该节点向右子树延伸的部分。
精选力扣500题 第36题 LeetCode 124. 二叉树中的最大路径和【c++ / java 详细题解】_第2张图片
我们可以递归遍历整棵树,递归时维护从每个子树从最高节点开始往下延伸的最大路径和。

  • 对于每个子树的最高节点,递归计算完左右子树后,我们将左右子树维护的两条最大路径,和该点拼接起来,就可以得到以这个点为最高节点子树的最大路径。(这条路径一定是:左子树路径->最高节点->右子树路径
  • 然后维护从这个点往下延伸的最大路径:从左右子树的路径中选择权值大的一条延伸即可。(只能从左右子树之间选一条路径

最后整颗树的最大路径和为: 根节点值+左子树最大路径和+右子树最大路径和,即left_max + right_max + root->val

注意: 如果某条路径之和小于0,那么我们选择不走该条路径,因此其路径之和应和0之间取最大值。

时间复杂度分析: 每个节点仅会遍历一次,所以时间复杂度是 O ( n ) O(n) O(n)

3、c++代码

/**
 * Definition for a binary tree node.
 * 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 {
public:
    int ans;
    int maxPathSum(TreeNode* root) {
        ans = INT_MIN;
        dfs(root);
        return ans;
    }
    int dfs(TreeNode* root)
    {
        if(!root) return 0;
        //计算左边分支最大值,左边分支如果为负数还不如不选择
        int left = max(0,dfs(root->left));
		//计算右边分支最大值,右边分支如果为负数还不如不选择
        int right = max(0,+dfs(root->right));
        //left->root->right 作为路径与已经计算过历史最大值做比较
        ans = max(ans,left + right + root->val);
        //返回经过root的单边最大分支给当前root的父节点计算使用
        return  root->val + max( left ,right);
    }
};

4、java代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int ans ;
    public int maxPathSum(TreeNode root) {
        ans = Integer.MIN_VALUE;
        dfs(root);
        return ans;
    }
    public int dfs(TreeNode  root)
    {
        if(root == null) return 0;
        int left = Math.max(0,dfs(root.left)),right = Math.max(0,+dfs(root.right));
        ans = Math.max(ans,left + right + root.val);
        return  root.val + Math.max( left ,right);
    }
}

原题链接: 124. 二叉树中的最大路径和
在这里插入图片描述

你可能感兴趣的:(LeetCode题解,二叉树,数据结构,leetcode,dfs,新星计划)