124. 二叉树中的最大路径和

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

所有树的题目,都想成一颗只有根、左节点、右节点 的小树。然后一颗颗小树构成整棵大树,所以只需要考虑这颗小树即可。接下来分情况, 按照题意:一颗三个节点的小树的结果只可能有如下6种情况:

  1. 根 + 左 + 右
  2. 根 + 左
  3. 根 + 右

好了,分析上述6种情况, 只有 2,3,4 可以向上累加,而1,5,6不可以累加(这个很好想,情况1向上累加的话,必然出现分叉,情况5和6直接就跟上面的树枝断开的,没法累加),所以我们找一个全局变量存储 1,5,6这三种不可累加的最大值, 另一方面咱们用遍历树的方法求2,3,4这三种可以累加的情况。 最后把两类情况得到的最大值再取一个最大值即可。

  1. //递归法
  2. func maxPathSum(root *TreeNode) int {
  3. maxSum := math.MinInt32 // 最大路径和,默认-2934950305495
  4. var dfs func(root *TreeNode) int
  5. dfs = func(root *TreeNode) int {
  6. if root == nil { // 遍历到null节点,收益0
  7. return 0
  8. }
  9. left := dfs(root.Left) // 左右子树提供的最大路径和
  10. right := dfs(root.Right)
  11. inputMaxSum := left + root.Val + right // 当前子树内部的最大路径和
  12. maxSum = max(maxSum, inputMaxSum)
  13. outputMaxSum := max(left, right) + root.Val // 当前子树对外提供的最大和
  14. return max(outputMaxSum, 0) // 对外提供的路径和为负,直接返回0。否则正常返回
  15. }
  16. dfs(root) // 递归的入口
  17. return maxSum
  18. }
  19. func max(a, b int) int {
  20. if a > b { return a }
  21. return b
  22. }