124. 二叉树中的最大路径和
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中至多出现一次 ==该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
所有树的题目,都想成一颗只有根、左节点、右节点 的小树。然后一颗颗小树构成整棵大树,所以只需要考虑这颗小树即可。接下来分情况, 按照题意:一颗三个节点的小树的结果只可能有如下6种情况:
- 根 + 左 + 右
- 根 + 左
- 根 + 右
- 根
- 左
- 右
好了,分析上述6种情况, 只有 2,3,4 可以向上累加,而1,5,6不可以累加(这个很好想,情况1向上累加的话,必然出现分叉,情况5和6直接就跟上面的树枝断开的,没法累加),所以我们找一个全局变量存储 1,5,6这三种不可累加的最大值, 另一方面咱们用遍历树的方法求2,3,4这三种可以累加的情况。 最后把两类情况得到的最大值再取一个最大值即可。
//递归法
func maxPathSum(root *TreeNode) int {
maxSum := math.MinInt32 // 最大路径和,默认-2934950305495
var dfs func(root *TreeNode) int
dfs = func(root *TreeNode) int {
if root == nil { // 遍历到null节点,收益0
return 0
}
left := dfs(root.Left) // 左右子树提供的最大路径和
right := dfs(root.Right)
inputMaxSum := left + root.Val + right // 当前子树内部的最大路径和
maxSum = max(maxSum, inputMaxSum)
outputMaxSum := max(left, right) + root.Val // 当前子树对外提供的最大和
return max(outputMaxSum, 0) // 对外提供的路径和为负,直接返回0。否则正常返回
}
dfs(root) // 递归的入口
return maxSum
}
func max(a, b int) int {
if a > b { return a }
return b
}