leet-code 所有二叉树路径问题

参考总结

二叉树路径的问题大致可以分为两类:
1、自顶向下:
顾名思义,就是从某一个节点(不一定是根节点),从上向下寻找路径,到某一个节点(不一定是叶节点)结束
具体题目如下:

257 从根到叶所有路径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
var res []string
var path []int
func binaryTreePaths(root *TreeNode) []string {
    //自顶向下,DFS前序遍历
    res=nil
    path=nil
    helper(root)
    return res
}
func helper(root *TreeNode){
    if root==nil{
        return 
    }
    path=append(path,root.Val)
    if root.Left==nil&&root.Right==nil{
        var finalRes string
        for i:=0;i<len(path)-1;i++{
            finalRes+=strconv.Itoa(path[i])+"->"
        }
        finalRes+=strconv.Itoa(path[len(path)-1])
        res=append(res,finalRes)
    }
    helper(root.Left)
    helper(root.Right)
    path=path[0:len(path)-1]//pop back
    return
}

112 从根到叶路径和满足目标值

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func hasPathSum(root *TreeNode, targetSum int) bool {
    if root==nil{
        return false
    }
    if root.Left==nil&&root.Right==nil{
        return root.Val==targetSum
    }
    return hasPathSum(root.Left,targetSum-root.Val)||hasPathSum(root.Right,targetSum-root.Val)
}

113 从根到叶路径和满足目标值的路径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
var res [][]int
var path[]int
func pathSum(root *TreeNode, targetSum int) [][]int {
    res=nil
    path=nil
    dfs(root,targetSum)
    return res
}

func dfs(root *TreeNode, targetSum int){
    if root==nil{
        return 
    }
    path=append(path,root.Val)
    targetSum-=root.Val
    if root.Left==nil&&root.Right==nil{
        //fmt.Println(root.Val,path,targetSum)
        if targetSum==0{
            var finalPath []int
            finalPath=append([]int(nil),path...)
            res=append(res,finalPath)
        }
    }
    dfs(root.Left,targetSum)
    dfs(root.Right,targetSum)
    path=path[0:len(path)-1]//pop back
    return
}

437 路径总和3,任意节点到节点,从上到下

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func pathSum(root *TreeNode, targetSum int) int {
    if root==nil{
        return 0
    }
    //先调用dfs函数从root开始查找路径,再调用pathsum函数到root左右子树开始查找这样实现从任意节点开始
    res:=helper(root,targetSum)
    res+=pathSum(root.Left,targetSum)
    res+=pathSum(root.Right,targetSum)
    return res
}

func helper(root *TreeNode, targetSum int)int{
    if root==nil{
        return 0
    }
    innerRes:=0
    targetSum-=root.Val
    //如果找到了一个路径全局变量就+1
    if targetSum==0{
        //fmt.Println("s",res)
        //注意不要return,因为不要求到叶节点结束,所以一条路径下面还可能有另一条
        innerRes++
    }
    innerRes+=helper(root.Left,targetSum)
    innerRes+=helper(root.Right,targetSum)
    return innerRes
}

988 从叶节点到根节点的最小字符串

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 var path[]string
var sliceStr= []string{"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
		"p","q","r","s","t","u","v","w","x","y","z"}
func smallestFromLeaf(root *TreeNode) string {
    path=nil
    dfs(root,"")
    //按小到大排序
    sort.Strings(path)
    return path[0]//字典序最小
}

func dfs(root *TreeNode, str string){
    if root==nil{
        return
    }
    str+=sliceStr[root.Val]
    if root.Left==nil&&root.Right==nil{
        //leave
        str=reverse(str)//题目要求从叶节点到根节点,因此反转
        path=append(path,str)
        return
    }
    dfs(root.Left,str)
    dfs(root.Right,str)
    return
}

func reverse(str string)string{
    var res string
    for i:=0;i<len(str);i++{
        res+=fmt.Sprintf("%c",str[len(str)-1-i])
    }
    return res
}

非自顶向下

这类题目一般解题思路如下:
设计一个辅助函数maxpath,调用自身求出以一个节点为根节点的左侧最长路径left和右侧最长路径right,那么经过该节点的最长路径就是left+right
接着只需要从根节点开始dfs,不断比较更新全局变量即可

这类题型DFS注意点:
1、left,right代表的含义要根据题目所求设置,比如最长路径、最大路径和等等

2、全局变量res的初值设置是0还是INT_MIN要看题目节点是否存在负值,如果存在就用INT_MIN,否则就是0

3、注意两点之间路径为1,因此一个点是不能构成路径的

124 二叉树中的最大路径和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 /*
 定义一个递归方法,从下到上递归,后续遍历。
 1. 每个节点的贡献:
    1.1 空节点的最大贡献值等于 0;
    1.2 非空节点的最大贡献值等于节点值与其子节点中的最大贡献值之和
 2. 每个接的的最大路径和:
    该节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值,如果子节点的最大贡献值为正,则计入该节点的最大路径和,否则不计入该节点的最大路径和。维护一个全局变量 maxSum 存储最大路径和,在递归过程中更新 maxSum 的值,最后得到的 maxSum 的值即为二叉树中的最大路径和
 参考:
    1.https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/cchao-jian-dan-li-jie-miao-dong-by-fengz-8l3m/
    2.https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/solution/er-cha-shu-zhong-de-zui-da-lu-jing-he-by-leetcode-/ 
 */
var maxV int
func maxPathSum(root *TreeNode) int {
    if root==nil{
        return 0
    }
    maxV=INTMIN
    dfs(root)
    return maxV
}
//通过后序遍历的方式,先计算出左右子树的最大路径和,然后再计算当前树的最大路径和
func dfs(root *TreeNode)int {
    if root==nil{
        return 0
    }
    //计算左边分支最大值,左边分支如果为负数还不如不选择
    leftV:=max(0,dfs(root.Left))
    //计算右边分支最大值,右边分支如果为负数还不如不选择
    rightV:=max(0,dfs(root.Right))
    //一个子树内部的最大路径和 = 左子树提供的最大路径和 + 根节点值 + 右子树提供的最大路径和,作为路径与已经计算过历史最大值做比较
    maxV=max(maxV,root.Val+leftV+rightV)
    //返回当前子树对外提供的贡献
    return root.Val+max(leftV,rightV)
}

func max(x,y int)int {
    if x<y{
        return y
    }
    return x
}
const INTMAX=int(^uint(0)>>1)
const INTMIN=^INTMAX

687 最长同值路径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 var res int
func longestUnivaluePath(root *TreeNode) int {
    res=0
    if root==nil{
        return res
    }
    longestPath(root)
    return res
}
func longestPath(root *TreeNode)int {
    if root==nil{
        return 0
    }
    leftV:=longestPath(root.Left)
    rightV:=longestPath(root.Right)
    // 如果存在左子节点和根节点同值,更新左最长路径;否则左最长路径为0
    if root.Left!=nil&&root.Val==root.Left.Val{
        leftV++
    }else{
        leftV=0
    }
    // 如果存在右子节点和根节点同值,更新右最长路径;否则右最长路径为0
    if root.Right!=nil&&root.Val==root.Right.Val{
        rightV++
    }else{
        rightV=0
    }
    res=max(res,leftV+rightV)
    return max(leftV,rightV)
}
func max(x,y int)int {
    if x<y {
        return y
    }
    return x
}

543 二叉树直径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 var res int=0
func diameterOfBinaryTree(root *TreeNode) int {
    res=0
    if root==nil{
        return res
    }
    maxPath(root)
    return res
}

func maxPath(root *TreeNode)int{
    if root.Left==nil&&root.Right==nil{
        return 0
    }
    var leftV int
    //判断左子节点是否为空,从而更新左边最长路径
    if root.Left!=nil{
        leftV=maxPath(root.Left)+1
    }else{
        leftV=0
    }
    var RightV int
    if root.Right!=nil{
        RightV=maxPath(root.Right)+1
    }else{
        RightV=0
    }
    res=max(res,leftV+RightV)//全局最长路径
    return max(leftV,RightV)//返回以root点开始能提供的最长路径
}

func max(x, y int)int {
    if x<y {
        return y
    }
    return x
}

563 二叉树坡度

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
var res int
func findTilt(root *TreeNode) int {
    res=0
    postorder(root)
    return res
}
//root节点可以提供的子树节点和
func postorder(root *TreeNode)int{
    if root==nil{
        return 0
    }
    left:=postorder(root.Left)
    right:=postorder(root.Right)
    cur:=abs(left-right)//root节点的左右子树的坡度,更新全局变量
    res+=cur
    return root.Val+left+right//root节点可以提供的子树节点和
}

func abs(x int)int {
    if x<0{
        return -1*x
    }
    return x
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值