概述
给出一棵二叉树。目标是找到该二叉树中的最大路径总和。 二叉树中的路径是一个相互连接的节点序列。每个节点在最大路径总和中只出现一次。
例子1
Output: 16
Maximum Sum Path is: 4->2->1->3->6
例2
Output: 14
Maximum Sum Path is: 5->3->6
我们的想法是在每个节点上跟踪以下四个值
-
a = root.Val
-
b = root.Val + leftSubTreeMaxSum
-
c = root.Val + rightSubTreeMaxSum
-
d = root.Val + leftSubTreeMaxSum+ rightSubTreeMaxSum
然后
-
给定节点的最大和是 (a,b,c,d) 的最大值。
-
递归调用的返回值将是 (a,b,c) 的最大值。 为什么呢?这是因为只有a或b或c的路径代表了在父节点上可以被考虑的路径。为了用一个例子来理解这一点,请考虑上面例子二中的二叉树。路径5->3->6不能将父节点 -5 纳入其路径中,因为它成为无效路径。
程序
下面是同样的程序
package main
import (
"fmt"
"math"
)
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func maxPathSum(root *TreeNode) int {
res := math.MinInt64
maxPathSumUtil(root, &res)
return res
}
func maxPathSumUtil(root *TreeNode, res *int) int {
if root == nil {
return 0
}
l := maxPathSumUtil(root.Left, res)
r := maxPathSumUtil(root.Right, res)
a := root.Val
b := root.Val + l
c := root.Val + r
d := root.Val + l + r
maxReturnSum := maxOfThree(a, b, c)
maxSumPath := maxOfTwo(maxReturnSum, d)
if maxSumPath > *res {
*res = maxSumPath
}
return maxReturnSum
}
func maxOfThree(a, b, c int) int {
if a > b && a > c {
return a
}
if b > c {
return b
}
return c
}
func maxOfTwo(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
root := &TreeNode{Val: 1}
root.Left = &TreeNode{Val: 2}
root.Left.Left = &TreeNode{Val: 4}
root.Right = &TreeNode{Val: 3}
root.Right.Left = &TreeNode{Val: 5}
root.Right.Right = &TreeNode{Val: 6}
output := maxPathSum(root)
fmt.Println(output)
root = &TreeNode{Val: -10}
root.Left = &TreeNode{Val: 2}
root.Left.Left = &TreeNode{Val: 4}
root.Right = &TreeNode{Val: 3}
root.Right.Left = &TreeNode{Val: 5}
root.Right.Right = &TreeNode{Val: 6}
output = maxPathSum(root)
fmt.Println(output)
}
输出:
16
14