前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2021-10-11:二叉树中的最大路径和。路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一

2021-10-11:二叉树中的最大路径和。路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一

作者头像
福大大架构师每日一题
发布2021-10-14 11:20:01
1.9K0
发布2021-10-14 11:20:01
举报

2021-10-11:二叉树中的最大路径和。路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。路径和 是路径中各节点值的总和。给你一个二叉树的根节点 root ,返回其 最大路径和 。力扣124。

福大大 答案2021-10-11:

递归。x是其中一个节点。

1.无x。

1.1.左树整体的maxsum。

1.2.右树整体的maxsum。

2.有x。

2.1.只有x

2.2.x+左树路径。

2.3.x+右树路径。

2.4.x+左树路径+右树路径。。

时间复杂度:O(N)。

空间复杂度:O(N)。

代码用golang编写。代码如下:

代码语言:javascript
复制
package main

import (
    "fmt"
    "math"
)

func main() {
    head := NewTreeNode(4)
    head.left = NewTreeNode(-7)
    head.right = NewTreeNode(-5)
    head.left.left = NewTreeNode(9)
    head.left.right = NewTreeNode(9)
    head.right.left = NewTreeNode(4)
    head.right.right = NewTreeNode(3)

    maxPath := getMaxSumPath(head)

    for _, n := range maxPath {
        fmt.Println(n.val)
    }
}

type TreeNode struct {
    val   int
    left  *TreeNode
    right *TreeNode
}

func NewTreeNode(v int) *TreeNode {
    res := &TreeNode{}
    res.val = v
    return res
}

func maxPathSum(root *TreeNode) int {
    if root == nil {
        return 0
    }
    return process(root).maxPathSum
}

// 任何一棵树,必须汇报上来的信息
type Info struct {
    maxPathSum         int
    maxPathSumFromHead int
}

func NewInfo(path0, head int) *Info {
    ans := &Info{}
    ans.maxPathSum = path0
    ans.maxPathSumFromHead = head
    return ans
}

func process(x *TreeNode) *Info {
    if x == nil {
        return nil
    }
    leftInfo := process(x.left)
    rightInfo := process(x.right)
    // x 1)只有x 2)x往左扎 3)x往右扎
    maxPathSumFromHead := x.val
    if leftInfo != nil {
        maxPathSumFromHead = getMax(maxPathSumFromHead, x.val+leftInfo.maxPathSumFromHead)
    }
    if rightInfo != nil {
        maxPathSumFromHead = getMax(maxPathSumFromHead, x.val+rightInfo.maxPathSumFromHead)
    }
    // x整棵树最大路径和 1) 只有x 2)左树整体的最大路径和 3) 右树整体的最大路径和
    maxPathSum := x.val
    if leftInfo != nil {
        maxPathSum = getMax(maxPathSum, leftInfo.maxPathSum)
    }
    if rightInfo != nil {
        maxPathSum = getMax(maxPathSum, rightInfo.maxPathSum)
    }
    // 4) x只往左扎 5)x只往右扎
    maxPathSum = getMax(maxPathSumFromHead, maxPathSum)
    // 6)一起扎
    if leftInfo != nil && rightInfo != nil && leftInfo.maxPathSumFromHead > 0 && rightInfo.maxPathSumFromHead > 0 {
        maxPathSum = getMax(maxPathSum, leftInfo.maxPathSumFromHead+rightInfo.maxPathSumFromHead+x.val)
    }
    return NewInfo(maxPathSum, maxPathSumFromHead)
}
func getMax(a int, b int) int {
    if a > b {
        return a
    } else {
        return b
    }
}

// 如果要返回路径的做法
func getMaxSumPath(head *TreeNode) []*TreeNode {
    ans := make([]*TreeNode, 0)
    if head != nil {
        data := f(head)
        fmap := make(map[*TreeNode]*TreeNode)
        fmap[head] = head
        fatherMap(head, fmap)
        fillPath(fmap, data.from, data.to, &ans)
    }
    return ans
}

type Data struct {
    maxAllSum  int
    from       *TreeNode
    to         *TreeNode
    maxHeadSum int
    end        *TreeNode
}

func NewData(a int, b *TreeNode, c *TreeNode, d int, e *TreeNode) *Data {
    res := &Data{}
    res.maxAllSum = a
    res.from = b
    res.to = c
    res.maxHeadSum = d
    res.end = e
    return res
}

func f(x *TreeNode) *Data {
    if x == nil {
        return nil
    }
    l := f(x.left)
    r := f(x.right)
    maxHeadSum := x.val
    end := x
    if l != nil && l.maxHeadSum > 0 && (r == nil || l.maxHeadSum > r.maxHeadSum) {
        maxHeadSum += l.maxHeadSum
        end = l.end
    }
    if r != nil && r.maxHeadSum > 0 && (l == nil || r.maxHeadSum > l.maxHeadSum) {
        maxHeadSum += r.maxHeadSum
        end = r.end
    }
    maxAllSum := math.MinInt64
    var from *TreeNode
    var to *TreeNode
    if l != nil {
        maxAllSum = l.maxAllSum
        from = l.from
        to = l.to
    }
    if r != nil && r.maxAllSum > maxAllSum {
        maxAllSum = r.maxAllSum
        from = r.from
        to = r.to
    }
    p3 := x.val
    if l != nil && l.maxHeadSum > 0 {
        p3 = x.val + l.maxHeadSum
    }

    if p3 > maxAllSum {
        maxAllSum = p3
        from = x
        if l != nil && l.maxHeadSum > 0 {
            from = l.end
        }
        to = x
        if r != nil && r.maxHeadSum > 0 {
            to = r.end
        }
    }
    return NewData(maxAllSum, from, to, maxHeadSum, end)
}

func fatherMap(h *TreeNode, map0 map[*TreeNode]*TreeNode) {
    if h.left == nil && h.right == nil {
        return
    }
    if h.left != nil {
        map0[h.left] = h
        fatherMap(h.left, map0)
    }
    if h.right != nil {
        map0[h.right] = h
        fatherMap(h.right, map0)
    }
}

func fillPath(fmap map[*TreeNode]*TreeNode, a *TreeNode, b *TreeNode, ans *[]*TreeNode) {
    if a == b {
        *ans = append(*ans, a)
    } else {
        ap := make(map[*TreeNode]struct{})
        cur := a
        for cur != fmap[cur] {
            ap[cur] = struct{}{}
            cur = fmap[cur]
        }
        ap[cur] = struct{}{}
        cur = b
        var lca *TreeNode
        for lca == nil {
            if _, ok := ap[cur]; ok {
                lca = cur
            } else {
                cur = fmap[cur]
            }
        }
        for a != lca {
            *ans = append(*ans, a)
            a = fmap[a]
        }
        *ans = append(*ans, lca)
        right := make([]*TreeNode, 0)
        for b != lca {
            right = append(right, b)
            b = fmap[b]
        }
        for i := len(right) - 1; i >= 0; i-- {
            *ans = append(*ans, right[i])
        }
    }
}

执行结果如下:

***

[左神java代码](https://github.com/algorithmzuo/coding-for-great-offer/blob/main/src/class30/Problem_0124_BinaryTreeMaximumPathSum.java)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档