【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);
}
};