[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题

目录

  • 双指针专题
    • 题目:判断两个树是否相同
      • 思路分析:递归 + 左对左、右对右 判断相等
      • Go代码
    • 题目:判断二叉树是否镜像对称的
      • 思路分析:递归 + 左对右、右对左 判断相等
      • Go代码
    • 题目:合并二叉树
      • 思路分析:递归 + 左对左、右对右 值相加
      • Go代码
  • 路径专题
    • 题目:找出二叉树的所有路径
      • 思路分析:递归 + 每个叶子节点对应一条路径
      • Go代码
    • 题目:判断二叉树中是否存在路径总和为指定值的路径
      • 思路分析:递归
      • Go代码
    • 题目:找出二叉树中路径总和为指定值的所有路径
      • 思路分析:递归 + defer巧妙处理
      • 递归图解
      • Go代码
  • 翻转专题
    • 题目:翻转二叉树
      • 思路分析:递归 + 左右节点互换
      • Go代码

双指针专题

题目:判断两个树是否相同

题目链接:LeetCode-100. 相同的树
[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第1张图片

思路分析:递归 + 左对左、右对右 判断相等

递归遍历这两颗二叉树,判断每个节点,只要存在值不同时就不是相同的树。

Go代码

func isSameTree(p *TreeNode, q *TreeNode) bool {
    if p == nil && q == nil {
        return true
    }
    if p == nil || q == nil {
        return false
    }
    if p.Val != q.Val {
        return false
    }
    return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}

题目:判断二叉树是否镜像对称的

题目链接:LeetCode-101. 对称二叉树
[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第2张图片

思路分析:递归 + 左对右、右对左 判断相等

根据镜像的定义,如果这是一个镜像二叉树,那只要把根节点去掉之后可以看做是两个完全对称的二叉树。
所以跟上一题做法基本一致,递归遍历每个子节点,只不过判断时不是左对左、右对右的判断,而是对称判断,即左对右,右对左,只要完全一致,则是对称的二叉树。

Go代码

func isSame(a, b *TreeNode) bool {
    if a == nil && b == nil {
        return true
    }
    if a == nil || b == nil {
        return false
    }
    return a.Val == b.Val && isSame(a.Left, b.Right) && isSame(a.Right, b.Left)
}

func isSymmetric(root *TreeNode) bool {
    if root == nil {
        return true
    }
    return isSame(root.Left, root.Right)
}

题目:合并二叉树

题目链接:LeetCode-617. 合并二叉树
[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第3张图片

思路分析:递归 + 左对左、右对右 值相加

同样递归遍历两个树,左对左,右对右,将值相加后赋给新的树节点即可。
注意判断节点为空时,直接取另一颗树对应结点赋值即可。

Go代码

func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    if root1 == nil && root2 == nil {
        return nil
    }
    if root1 == nil {
        return root2
    }
    if root2 == nil {
        return root1
    }
    newTree := &TreeNode{
        Val : root1.Val + root2.Val,
        Left : mergeTrees(root1.Left, root2.Left),
        Right : mergeTrees(root1.Right, root2.Right),
    }
    return newTree
}

路径专题

题目:找出二叉树的所有路径

题目链接:LeetCode-257. 二叉树的所有路径
[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第4张图片

思路分析:递归 + 每个叶子节点对应一条路径

Go代码

func binaryTreePaths(root *TreeNode) (res []string) {
    if root == nil {
        return nil
    }
    var a func(*TreeNode, string)
    a = func(node *TreeNode, path string) {
        if node == nil {
            return
        }
        str := fmt.Sprintf("%d", node.Val)
        path = path+str
        // 叶子节点
        if node.Left == nil && node.Right == nil {
            res = append(res, path)
            return
        }
        a(node.Left, path+"->")
        a(node.Right, path+"->")
    }
    a(root, "")
    return
}

题目:判断二叉树中是否存在路径总和为指定值的路径

题目链接:LeetCode-112. 路径总和
[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第5张图片

思路分析:递归

路径总和向下传递的时候减去当前节点的值,这样只要判断是叶子节点并且叶子节点的值等于当时的参数路径总和即代表存在目标路径。

Go代码

func hasPathSum(root *TreeNode, targetSum int) bool {
    if root == nil {
        return false
    }
    if root.Left == nil && root.Right == nil && root.Val == targetSum {
        return true
    }
    return hasPathSum(root.Left, targetSum-root.Val) || hasPathSum(root.Right, targetSum-root.Val)
}

题目:找出二叉树中路径总和为指定值的所有路径

题目链接:LeetCode-113. 路径总和 II
[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第6张图片

思路分析:递归 + defer巧妙处理

递归图解

[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第7张图片

Go代码

func pathSum(root *TreeNode, targetSum int) (res [][]int) {
    if root == nil {
        return
    }
    arr := []int{}
    var a func(*TreeNode, int)
    a = func (node *TreeNode, sum int) {
        if node == nil {
            return
        }
        sum -= node.Val
        arr = append(arr, node.Val)
        // 从最左叶子节点开始往回遍历时,将该节点从arr中取出
        // 这样能确保arr中的节点数组是从根节点到当前节点的路径节点
        defer func() { arr = arr[:len(arr)-1] }()
        // 找到一条路径
        if node.Left == nil && node.Right == nil && sum == 0 {
            // append([]int{}, arr...) 将arr的元素都放在一个新的切片中加入到res,
            // 否则如果直接将arr将入到res,后面对arr的修改都会同步到res中
            res = append(res, append([]int{}, arr...))
            return
        }
        a(node.Left, sum)
        a(node.Right, sum)
    }
    a(root, targetSum)
    return
}

翻转专题

题目:翻转二叉树

题目链接:LeetCode-226. 翻转二叉树
[Go版]算法通关村第八关青铜——轻松搞定二叉树的深度优先经典问题_第8张图片

思路分析:递归 + 左右节点互换

只需要将每个节点的左右节点互换即可完成翻转。

Go代码

func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return root
    }
    root.Left, root.Right = root.Right, root.Left
    invertTree(root.Left)
    invertTree(root.Right)
    return root
}

你可能感兴趣的:(算法与数据结构,算法,golang,深度优先)