来自leetcode124:二叉树中的最大路径和https://leetcode.cn/problems/binary-tree-maximum-path-sum/
这道题乍一看很难,又不一定经过根,还能“拐弯” ,但是二叉树问题嘛,不是广度遍历和树形dp的话,那就只有递归了。
首先搞清楚“路径”的定义,即从一个节点出发,到达另一个节点,每个节点遍历一次即可遍历到所有节点。
然后我们思考,那这个路径是不是一定要有个根呢?是的,因为至少有一个节点,就算只有一个节点,我们也可以将这个节点认作根。这样我们思考,对于每个节点,我们是不是只需要找到其左右叶子的最大贡献值,就可以求出这个最大路径了呢?所以递归就是在求到达当前节点的一侧的最大值,并且在递归中,我们可以得到左右节点的侧最大值,就可以计算出以当前节点为根的最值,在遍历过程中比较置换,最后即可找到最大值:
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
var maxNum int
func maxPathSum(root *TreeNode) int {
maxNum = -30000001
getSideMax(root)
return maxNum
}
func getSideMax(root *TreeNode) int {
if root.Left == nil && root.Right == nil {
if root.Val > maxNum {
// 比较最大值
maxNum = root.Val
}
// 返回一侧的最值
return root.Val
}
leftSideMax := 0
rightSideMax := 0
if root.Left != nil {
leftSideMax = getSideMax(root.Left)
}
if root.Right != nil {
rightSideMax = getSideMax(root.Right)
}
nodeMax := root.Val
// 比较最大值
if leftSideMax > 0 {
nodeMax = nodeMax + leftSideMax
}
if rightSideMax > 0 {
nodeMax = nodeMax + rightSideMax
}
if nodeMax > maxNum {
maxNum = nodeMax
}
sideMax := int(math.Max(float64(leftSideMax), float64(rightSideMax)))
// 返回一侧的最值
if sideMax > 0 {
return root.Val + sideMax
} else {
return root.Val
}
}
求当前节点侧最大值时,先找到其左右节点的侧最大值,如果这个最值都小于0,那就没必要加子树了,直接返回当前节点值作为侧最大值即可,否则就返回当前节点值加上侧最值,并返回,在这个过程中,别忘了求以当前节点为根的最大路径值,这个是以当前跟节点值为基石,如果左右子树的侧最值大于0,就加上作为路径,求出这个值后,可以与当前Max比较置换,一次遍历即可求出最值!