Hard
题目描述
二叉树中的路径被定义为一条从树中任意节点出发,沿父子连接,达到任意节点的序列。同一个节点在一条路径序列中至多出现一次。该路径至少包含一个节点,且不一定经过根节点。
路径和是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其最大路径和。
示例 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 * 10^4] -1000 <= Node.val <= 1000
解题思路
这道题的关键在于理解路径的定义:路径可以从任意节点开始,到任意节点结束,不一定经过根节点。我们需要考虑所有可能的路径组合。
核心思路:
使用递归的深度优先搜索,对于每个节点,考虑以该节点为"拐点"的最大路径和。一条经过节点的路径可以分为三部分:左子树路径 + 当前节点 + 右子树路径。
递归函数设计:
设计递归函数 maxGain(node),返回以该节点为起点的单边最大路径和(只能向左或向右,不能同时向两边)。这样设计是因为如果一个节点要作为其父节点路径的一部分,它只能贡献单边路径。
状态更新:
在每个节点处,计算经过该节点的最大路径和:left_gain + node.val + right_gain,并更新全局最大值。但要注意,负的贡献应该被忽略(取0)。
边界处理:
空节点返回0。对于叶子节点,其最大贡献就是节点值本身(如果为正)或0(如果为负)。
这种方法确保了每个可能的路径都被考虑到,时间复杂度为O(n),空间复杂度为O(h),其中h是树的高度。
代码实现
class Solution {
private:
int maxSum;
int maxGain(TreeNode* node) {
if (!node) return 0;
int leftGain = max(maxGain(node->left), 0);
int rightGain = max(maxGain(node->right), 0);
int currentMax = node->val + leftGain + rightGain;
maxSum = max(maxSum, currentMax);
return node->val + max(leftGain, rightGain);
}
public:
int maxPathSum(TreeNode* root) {
maxSum = INT_MIN;
maxGain(root);
return maxSum;
}
};
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
self.max_sum = float('-inf')
def max_gain(node):
if not node:
return 0
left_gain = max(max_gain(node.left), 0)
right_gain = max(max_gain(node.right), 0)
current_max = node.val + left_gain + right_gain
self.max_sum = max(self.max_sum, current_max)
return node.val + max(left_gain, right_gain)
max_gain(root)
return self.max_sum
public class Solution {
private int maxSum;
public int MaxPathSum(TreeNode root) {
maxSum = int.MinValue;
MaxGain(root);
return maxSum;
}
private int MaxGain(TreeNode node) {
if (node == null) return 0;
int leftGain = Math.Max(MaxGain(node.left), 0);
int rightGain = Math.Max(MaxGain(node.right), 0);
int currentMax = node.val + leftGain + rightGain;
maxSum = Math.Max(maxSum, currentMax);
return node.val + Math.Max(leftGain, rightGain);
}
}
var maxPathSum = function(root) {
let maxSum = -Infinity;
function maxGain(node) {
if (!node) return 0;
const leftGain = Math.max(maxGain(node.left), 0);
const rightGain = Math.max(maxGain(node.right), 0);
const currentMax = node.val + leftGain + rightGain;
maxSum = Math.max(maxSum, currentMax);
return node.val + Math.max(leftGain, rightGain);
}
maxGain(root);
return maxSum;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历树中的每个节点一次,其中 n 是节点数 |
| 空间复杂度 | O(h) | 递归调用栈的深度,其中 h 是树的高度,最坏情况下为 O(n) |
相关题目
. Path Sum (Easy)
. Sum Root to Leaf Numbers (Medium)
. Path Sum IV (Medium)
. Longest Univalue Path (Medium)