LeetCode124 二叉树中的最大路径和

61 阅读2分钟

leetcode.cn/problems/bi…

image.png

解法一:基于分解子问题思维模式的递归

最小子问题结构:考虑这样一个二叉树单元

  • a 作为当前root,与更上层的父节点相连接
  • b, c 作为左右子节点,与各自的左右子树中最大路径和的子节点相连接

image.png

那么,现在这个二叉树单元的最大路径和答案就在下面3选1:

  1. 左分支:b + a(+ a的父节点)
  2. 右分支:c + a (+ a的父节点)
  3. 左中右:b + a + c(不再连接a的更上层父节点)

情况1和2,可以分解子问题,递归,选择较大分支

但是情况3无法递归,我们可以用一个全局变量来记录,因为每当我们遍历到一个节点root时,我们能通过递归获取到其左右子树计算好的各自最大路径和了,这时候我们再算一下 left->root->right 这条路径和,更新到一个全局最大和变量中。

注意:节点值可能为负数,答案是要求最大值,那么遇到负数肯定是舍弃。但是,无论上面哪种情况,都需要经过 a,因此 a即使为负数也不能直接舍弃,我们定义全局最大和辅助变量的初始值采用minInt,才能保证和负数 a也正确比较。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxPathSum(root *TreeNode) int {
    if root == nil{
        return 0
    }
    res := math.MinInt
    _ = maxRootSum(root, &res)
    return res
}

// maxRootSum()返回经过root的单边分支最大和,即左、右分支中路径和较大值+当前root节点值
// 同时,还要考虑左中右的一种路径,借助一个变量记录在递归时记录好全局最大和
func maxRootSum(root *TreeNode, maxPathSum *int) int{
    if root == nil{
        return 0
    }
    //计算左边分支最大值,左边分支如果为负数还不如不选择
    leftMax := max(0, maxRootSum(root.Left, maxPathSum))
    //计算右边分支最大值,右边分支如果为负数还不如不选择
    rightMax := max(0, maxRootSum(root.Right, maxPathSum))
    //考虑左中右这条路径,left->root->right 路径和与已经计算过的全局最大和比较
    *maxPathSum = max(*maxPathSum, root.Val + leftMax + rightMax)
    // 返回经过当前root的单边分支最大和,给当前root的父节点递归计算使用
    return root.Val + max(leftMax, rightMax)
}

func max(a, b int) int{
    if a > b {
        return a
    }
    return b
}