二叉搜索树相关题目

669.修剪二叉搜索数

题目链接/文章讲解: https://programmercarl.com/0669.%E4%BF%AE%E5%89%AA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html

视频讲解: https://www.bilibili.com/video/BV17P41177ud

在这里插入图片描述

本题虽然也涉及到删除节点,但是与450那题做法其实并不类似,因为450那题删除节点后我们就需要重构一下二叉树然后返回左右节点即可,但是本题我们并不是只删除一个节点,我们删除了一个节点后还是要继续判断剩余节点

思路:例如:区间在[4,7],[low,high]

  1. 如果待删除节点<low,根据二叉搜索树的特性,那么待删除节点的左孩子节点,就可以全部抛弃,只需要去遍历判断右孩子即可,最后将处理好的右孩子节点向上返回
  2. 待删除节点>high,同理
  3. 同时本题虽然是二叉搜索树,但是我们依然要遍历整棵树,因为我们无法根据二叉搜索树的特性来判断到底应该怎么遍历
class Solution {
    // 返回值:是TreeNode,因为我们需要返回删除后的新的根节点,最后用父节点来连接,接收
    // 参数:不断遍历的节点,区间
    public TreeNode trimBST(TreeNode root, int low, int high) {
        if(root == null) return null;
        // 因为二叉搜索树的特性
        // 如果删除节点 < 左边界,那么删除节点的右边界就可能符合要求
        if(root.val < low){
            // trimBST(root.right,low,high):表示例如以2为根节点的情况下(区间还是在[4,7])
            // 左孩子我们已经可以直接抛弃,只用去判断右孩子,然后判断完之后
            // 我们就直接可以把处理好的右孩子节点返回,下面会有代码即节点7.left来接收
            TreeNode right = trimBST(root.right,low,high);
            return right;
        }
        // 同理
        if(root.val > high){
            TreeNode left = trimBST(root.left,low,high);
            return left;
        }
		
        // 在这里,就会接收到处理好的右孩子节点,
        // 节点7.left直接指向了节点4(待删除节点的右孩子),这里就相当于把节点2删除,因为节点2和节点7的连接被切断
        root.left = trimBST(root.left,low,high);
        root.right = trimBST(root.right,low,high);
        return root;
    }
}

108.将有序数组转换成二叉搜索树

https://programmercarl.com/0108.%E5%B0%86%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E8%BD%AC%E6%8D%A2%E4%B8%BA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html

视频讲解:https://www.bilibili.com/video/BV1uR4y1X7qL

思路:首先题目要求,是一颗平衡二叉搜索树,那么我们就不能直接一条向右不断创建节点

  • 既然要求平衡那么肯定就要不断从数组中间开始切割,在不断切割左右孩子最后创建的就是一个平衡二叉搜索树
  • 返回值:我们既然要创建节点还要向上返回,那返回值就是TreeNode
  • 参数:要不断切割数组,我们就可以利用双指针来切割,会比在原数组切割效率更高
  • 终止条件:只要数组为空,就不在创建节点,直接返回
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return sort(nums,0,nums.length-1);
    }

    public TreeNode sort(int[] nums, int start, int end){
        // 如果为空节点就返回null,那么就是数组中没有元素即start > end
        if(start > end) return null;

        // 取数组中间索引
        int mid = (start + end) >>> 1;
        // 根据中间索引创建节点
        TreeNode cur = new TreeNode(nums[mid]);
        // 创建左孩子
        cur.left = sort(nums,start,mid-1);
        // 创建右孩子
        cur.right = sort(nums,mid+1,end);
        return cur;
    }
}

538.把二叉搜索树转换为累加树

https://programmercarl.com/0538.%E6%8A%8A%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E8%BD%AC%E6%8D%A2%E4%B8%BA%E7%B4%AF%E5%8A%A0%E6%A0%91.html

视频讲解:https://www.bilibili.com/video/BV1d44y1f7wP

在这里插入图片描述

题目分析:首先要理解什么是累加树,就是把比我当前节点大的值都相加起来,例如根节点4,就是把整个右孩子节点的值都要相加包括4(即:4+6+5+7+8=30)

理解后思路就非常简单,二叉搜索树利用中序遍历后本身就是有序的,那么我们只要从后往前相加就可以计算出来,在二叉树中体现出来就是,先遍历右边,再处理中间,最后遍历左边,就是跟中序遍历相反。

// 双指针法
class Solution {
    // 记录前一个节点
    TreeNode per = null;
    public TreeNode convertBST(TreeNode root) {
        if(root == null) return null;

        convertBST(root.right);
        if(per !=null) root.val += per.val;
        per = root;
        convertBST(root.left);

        return root;
    }
}

t.val += per.val;
per = root;
convertBST(root.left);

    return root;
}

}


  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值