二叉树专题

二叉树基础知识

    可以点击这篇《go实现”二叉树遍历“》复习二叉树相关的知识点。

144. 二叉树的前序遍历

解题思路:

二叉树里的先:指的是中间节点遍历的顺序

中间节点先遍历,先序遍历

中间节点在中间,中序遍历

中间节点在最后,后序遍历

go语言里有点小坑,数组传递时候要传递地址。如果不传递数组地址,那么要覆盖当前数组值。

不传地址的方式

func preorderTraversal(root *TreeNode) []int {
    r := make([]int, 0, 4)
    return traversal(root, r)
}

func traversal(node *TreeNode, vals []int) []int {
    if node == nil {
        return vals
    }
    vals = append(vals, node.Val)
    vals = traversal(node.Left, vals)
    vals = traversal(node.Right, vals)
    return vals
}

传递地址的方式

func preorderTraversal(root *TreeNode) []int {
    r := make([]int, 0, 4)
    return *traversal(root, &r)
}

func traversal(node *TreeNode, vals *[]int) *[]int {
    if node == nil {
        return vals
    }
    *vals = append(*vals, node.Val)
    traversal(node.Left, vals)
    traversal(node.Right, vals)
    return vals
}

226. 翻转二叉树

解题思路:

   和二叉树遍历是一样的,只不过这里换成子节点的对换

func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return root
    }
    stack := []*TreeNode{}
    stack = append(stack, root)
    for len(stack) > 0 {
        node := stack[len(stack)-1]
        stack = stack[:len(stack) - 1]
        if node != nil {
            node.Left, node.Right = node.Right, node.Left
            stack = append(stack, node.Left)
            stack = append(stack, node.Right)
        }
    
    }
    return root
}

104. 二叉树的最大深度

解题思路:

本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。

  • 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
  • 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

110. 平衡二叉树

解题思路:

平衡二叉树需要满足的条件:

1. 左子树和右子树的高度差要 <= 1

2. 任意节点都要满足这个条件

那么这个题用递归分别求左右子树高度即可

func isBalanced(root *TreeNode) bool {
    // 如果是空左右子树都为空,高度差肯定<=1符合条件了
    if root == nil {
        return true
    }
    // 1. 递归求解左子树和右子树高度并判断高度差是否符合要求
    // 2. 任意一个节点都要满足左右子树高度差<=1
    return abs(height(root.Left) - height(root.Right)) <= 1 && isBalanced(root.Left) && isBalanced(root.Right)
}

func height(root *TreeNode) int {
    // 如果为空,那么这个节点高度为0
    if root == nil {
        return 0
    }
    // 求解当前节点左右子树的高度差
    return max(height(root.Left), height(root.Right)) + 1
}

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

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

654. 最大二叉树

解题思路

1. 创建树一般使用前序遍历(先填充根节点)

func constructMaximumBinaryTree(nums []int) *TreeNode {
    if len(nums) == 0 {
        return nil
    }
    best := 0
    for i := range nums {
        if nums[i] > nums[best] {
            best = i
        }
    }
    // go的数组为左闭右开
    return &TreeNode{nums[best], constructMaximumBinaryTree(nums[:best]), constructMaximumBinaryTree(nums[best+1:])}
}

单调栈解法:

func constructMaximumBinaryTree(nums []int) *TreeNode {
    tree := make([]*TreeNode, len(nums)) // 可以认为是一个缓存,key是栈保存的数组索引
    stk := []int{} // 栈结构,记录索引
    for i, num := range nums {
        // 根据当前遍历值生成一个新节点
        tree[i] = &TreeNode{Val: num}
        // 和栈上的值对比,如果当前值大于栈顶顶值,栈顶节点应该作为当前节点的左子树
        for len(stk) > 0 && num > nums[stk[len(stk)-1]] {
            tree[i].Left = tree[stk[len(stk)-1]]
            stk = stk[:len(stk)-1] // 从栈顶弹出
        }
        // 如果栈顶数据大于当前值,当前值把当前新节点挂到栈顶节点右侧
        if len(stk) > 0 {
            tree[stk[len(stk)-1]].Right = tree[i]
        }
        // 新索引位置
        stk = append(stk, i)

    }
    return tree[stk[0]]
}

530. 二叉搜索树的最小绝对差

func getMinimumDifference(root *TreeNode) int {
    var ans, pre = math.MaxInt64, -1
    var dfs func(*TreeNode)
    dfs = func(node *TreeNode) {
        if node == nil { 
            return 
        }
        dfs(node.Left)
        if pre != -1 && node.Val - pre < ans {
            ans = node.Val - pre
        }
        pre = node.Val
        dfs(node.Right)
    }
    dfs(root)
    return ans
}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值