[Go版]算法通关村第九关黄金——透彻理解二叉树中序遍历的应用【二叉搜索树的插入和删除操作】

题目:将有序数组转换为二叉搜索树

题目链接:LeetCode-108. 将有序数组转换为二叉搜索树
在这里插入图片描述

思路分析:数组中间数作为根节点

二叉搜索树特点:根左侧所有子节点值<根节点值<根右侧所有子节点值
升序排列的数组,其中间数可作为根节点
然后对数组范围缩小至:左边一半,右边一半。
这就构成了递归。

Go代码

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sortedArrayToBST(nums []int) *TreeNode {
    length := len(nums)
    if length == 0 {
        return nil
    }
    left, right := 0, length-1
    mid := (right-left)>>1+left
    return &TreeNode{
        Val: nums[mid],
        Left: sortedArrayToBST(nums[:mid]),
        Right: sortedArrayToBST(nums[mid+1:]),
    }
}

题目:二叉搜索树中的插入操作

题目链接:LeetCode-701. 二叉搜索树中的插入操作
在这里插入图片描述

思路分析:二叉搜索树的插入总是存在一个不需要调整树结构,就能插入新节点的位置

  • 二叉搜索树特点:根左侧所有子节点值<根节点值<根右侧所有子节点值
  • 二叉搜索树特点:对于普通二叉搜索树的插入,在不考虑平衡性问题时,总是存在一个不需要调整树结构,就能插入新节点的位置(本质是将新节点插入到叶子节点,而不会破坏整个树的有序性质)。
  1. 根据插入值val与root.Val比较大小,得知其应该插入在root的左侧还是右侧。
  2. 递归确定位置之后,赋值为新节点即可。

Go代码

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func insertIntoBST(root *TreeNode, val int) *TreeNode {
    if root == nil {
        root = &TreeNode{Val:val}
        return root
    }
    if root.Val > val {
        root.Left = insertIntoBST(root.Left, val)
    } else {
        root.Right = insertIntoBST(root.Right, val)
    }
    return root
}

题目:删除二叉搜索树中的节点

题目链接:LeetCode-450. 删除二叉搜索树中的节点
在这里插入图片描述

思路分析:分析删除节点的子树的4种情况

  • 二叉搜索树特点:根左侧所有子节点值<根节点值<根右侧所有子节点值
  1. 根据删除值val与root.Val比较大小,得知其应该在root的左侧还是右侧,递归直到找到该节点。
  2. 该节点的子树可能的4种情况:
    1. 该节点是叶子节点:返回nil 给其父节点即可。
    2. 该节点只有左子树:返回其左子树给其父节点即可。
    3. 该节点只有右子树:返回其右子树给其父节点即可。
    4. 该节点左右子树都存在:(有两种做法)
      1. 返回其左子树给其父节点:在返回之前,将其右子树接到其左子树的最右子节点的Right上。
      2. 返回其右子树给其父节点:在返回之前,将其左子树接到其右子树的最左子节点的Left上。

Go代码

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func deleteNode(root *TreeNode, key int) *TreeNode {
    if root == nil {
        return root
    }
    if root.Val > key { // 删除节点在左子树
        root.Left = deleteNode(root.Left, key)
    } else if root.Val < key {  // 删除节点在右子树
        root.Right = deleteNode(root.Right, key)
    } else {
        // 删除的节点:只有左子树 或右子树 或都没有
        if root.Left == nil || root.Right == nil {
            if root.Left != nil {
                return root.Left
            }
            return root.Right
        } else {    // 删除的节点存在左右子树            
            cur := root.Left
            // 目前root.Left和root.Right是同一级的,这里如果返回root.Left,就需要把root.Right接到root.Left的右侧最大子节点上
            // 反之如果要返回root.Right,就需要把root.Left接到root.Right的左侧最小子节点上
            for cur.Right != nil {
                cur = cur.Right
            }
            cur.Right = root.Right
            return root.Left
        }
    }
    return root
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值