【LeetCode-树】二叉树中的最大路径和

题目描述

给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
示例:

输入: [1,2,3]

       1
      / \
     2   3
输出: 6

输入: [-10,9,20,null,null,15,7]
   -10
   / \
  9  20
    /  \
   15   7
输出: 42

题目链接: https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/

思路

使用递归来做。需要注意的是:

  • 路径不一定通过根节点;
  • 路径不一定经过叶子节点;
  • 路径最少可以只包含 1 个节点;

因为不一定通过根节点,所以遍历整棵树,将当前节点作为根节点求解并记录路径的最大值。代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxPathSum(TreeNode* root) {
        if(root==nullptr) return 0;

        queue<TreeNode*> q;
        q.push(root);
        int curMax = INT_MIN;
        while(!q.empty()){
            TreeNode* node = q.front(); q.pop();
            int level = 0;
            curMax = max(curMax, dfs(node, level));
            curMax = max(curMax, node->val); // 可能只包含一个节点
            if(node->left!=nullptr) q.push(node->left);
            if(node->right!=nullptr) q.push(node->right);
        }
        return curMax;
    }

    int dfs(TreeNode* root, int level){
        if(root==nullptr) return 0;
        if(root->left==nullptr && root->right==nullptr) return root->val;
        
        if(level==0){
            int leftLen = dfs(root->left, level+1); // 根节点左子树的长度
            int rightLen = dfs(root->right, level+1);  // 根节点右子树的长度
            int len1 = root->val + leftLen;  // 根节点+左子树的长度
            int len2 = root->val + rightLen;  // 根节点+右子树的长度
            int len3 = root->val + leftLen + rightLen;  // 根节点+左子树+右子树的长度
            return max(max(len1, len2), len3); // 返回 3 个长度的最大值
        }else{
            /*返回当前根节点和当前根节点与左右子树路径最大值之和的最大值,因为不一定通过叶子节点*/
            return max(root->val, root->val + max(dfs(root->left, level+1), dfs(root->right, level+1)));
        }
    }
};

其中的 level 表示当前的层数。如果当前是第一层(level==0,根节点)那么就要求 3 个长度的最大值;如果不在第一层,则求左右子树的最大值就行了,因为最多只能走左子树或者右子树,不会两边都走。

简化写法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    int ans = INT_MIN;
public:
    int maxPathSum(TreeNode* root) {
        if(root==nullptr) return 0;
        dfs(root);
        return ans;
    }

    int dfs(TreeNode* root){
        if(root==nullptr) return 0;

        //计算左边分支最大值,左边分支如果为负数还不如不选择
        int leftMax = max(0, dfs(root->left));

        //计算右边分支最大值,右边分支如果为负数还不如不选择
        int rightMax = max(0, dfs(root->right));

        //left->root->right 作为路径与历史最大值做比较
        ans = max(ans, root->val+leftMax+rightMax);

        // 返回经过root的单边最大分支给上游
        return root->val + max(leftMax, rightMax);
    }
};

参考

简化写法参考了:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/er-cha-shu-zhong-de-zui-da-lu-jing-he-by-ikaruga/313184

posted @ 2020-06-21 16:50  Flix  阅读(487)  评论(0编辑  收藏  举报