算法题解记录25+++验证二叉搜索树(百日筑基)

news2024/11/27 22:33:18

题目描述:

        难度:中等

        给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左

    子树

    只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:root = [2,1,3]
输出:true

示例 2:

输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

提示:

  • 树中节点数目范围在[1, 10^4] 内
  • -2^31 <= Node.val <= 2^31 - 1

解题准备:

        1.题意:题目要求验证一棵二叉树,是不是二叉搜索树(BST,即Binary Search Tree),那么我们首先要知道,一棵二叉搜索树是什么样的。

        简单地说,BST有如下性质:第一,其左子树上所有节点的值,都小于根节点值;第二,其右子树上所有节点的值,都大于根节点的值。第三,BST下所有节点,都有BST的性质。

        2.基本操作:就题目看,不涉及增删改,验证必然要涉及查找遍历,姑且认为只有查找和比较。

        3.基础原理:面对树的题目,我们应敏锐地察觉到至少两种方法---BFS广度优先搜索和DFS深度优先搜索。这两种方法几乎是树的算法的基础,大多数算法,都是在二者之上优化而得。

解题思路:

        朴素地说,对于新手,其实一看到这个题目,是不会有什么思路的。

        然而,如果说做过一些题,就能直接得到答案,也非常夸张。

        我在此分享我的错误思路。

        错误思路---左右递归判断

                我最开始的思路比较简单,基于两个基本原理:

                第一,如果一棵树左子节点left的值,大于或等于根节点root的值,说明它不是BST。

                第二,如果一棵树右子节点right的值,小于或等于根节点root的值,说明不是BST。

                这两个原理没有错,却不完全,如果一棵树满足这两个原理,也有可能不是BST,比如下图,7大于5,却满足这个原理,同样,3小于5,也满足这个原理。

                这两个原理没有满足整体,所以我编写的代码在运行之后也报错了,不过,我会在下面提供代码。我先在此说明我的思考过程。【如何将这两个原理转化为代码的】

                第一步,有了原理,尽量往dfs或者bfs方法上靠近。

                第二步,发现判断一个节点是否满足2个原理,只需要判断left与root的关系、right与root的关系即可。【异常处理还没做】

                第三步,得到问题:虽然判断一个节点很简单,怎么判断下一个呢?

                第四步,初始的朴素思想:干脆中序遍历或前序遍历一遍,得到所有节点(存储List),依次进行判断?

                第五步,想到优化思路,既然中序遍历能够遍历每个节点,为什么要遍历一边,然后又从List再遍历一遍?

                第六步,中序原理是左根右,访问操作只在根节点做,那么继续左中右方法,把判断左子放在“左”,判断右子放在“右”,根节点的数据访问忽略了,就可以了。

                第七步,异常:访问到空节点null。

                第八步:if限制,null节点直接返回,又因为要判断子节点与根节点的关系,返回明显不能处理,所以需要额外判断子节点是否为null。

                完成。

        正确思路---中序遍历序列

                这个思路首先要明白一件事:中序遍历,其顺序是左子树、根节点、右子树。

                其中,在左子树left中,其顺序也是left的左子树、left、left的右子树。

                如果一棵树只有一个节点,毫无疑问它是升序的。

                假设这棵树root,它的左子树是left,右子树是right。

                那么,中序遍历时,一定会访问到left的最左子节点X,它是升序的。

                接着,访问最左子节点的父节点F,由于BST性质,最左子X小于F,所以是升序的。

                然后,访问F的右子【也有可能是右子的左子、右子的左子的左子……】P,由于BST性质,XFP升序排列。

                由于这棵树升序排列,那么,它的父树也升序排列,最后,left升序排列,整个节点的中序序列,都升序排列。

                由此,我们只需要得到中序序列,即可判断。

        正确思路---区间逼近

                这个思路是题解的思路,不过与我的错误思路非常接近,它把我的2个原理推进了。

                原理1:左子节点left,一定比root小,左子的左子,一定比root小;左子的右子,一定比root小,并且比左子大……

                原理2:右子节点right,一定比root大,右子的右子,一定比root大;右子的左子,一定比root大,并且比右子小。

                如此,我们可以发现,我的错误思路,就在于判断时,只是把节点与其左右子进行判断,忽略了最重要的根节点。

                然而,问题出现了:如果我们持续用root的值,作为判断依据,如下图:5作为右边所有节点的下限,没有问题,但是9却比7要大,也就是说子树7不符合BST的性质,所以整棵树不是BST。

                换句话说,我们要求上下限是不断变化的,这其实也是二叉树的精髓部分。

                怎么做呢?

                一般的想法是,维护两个变量low、up,使它们代表某个节点的上下限,在每次判断时作为依据。

                不过,如果这两个变量只是代表1个节点上下限,那么我们要开辟一个非常大的空间,用来存储所有的变量对low、up。

                所以,借助递归的方案,我们把维护变量对的操作交给系统,我们只需要递归调用时,传递变量对即可。

解题难点分析:

        无

错误代码---我的思路:

class Solution {
    public boolean isValidBST(TreeNode root) {
        boolean flag = true;
        // 为null不判断
        if(root.left!=null){
            if(root.left.val>=root.val){
                return false;
            }
            flag = isValidBST(root.left);
        }
        // 看一下是否不是BST
        if(!flag){
            return flag;
        }
        // 同理
        if(root.right!=null){
            if(root.right.val<=root.val){
                return false;
            }
            flag = isValidBST(root.right);
        }

        return flag;
    }
}

代码---中序遍历:

class Solution {
    public boolean isValidBST(TreeNode root) {
        // 存储节点
        List<Integer> data = new ArrayList<>();
        fuzhu(root, data);
        // 依次判断
        for(int i=0; i<data.size()-1; i++){
            if(data.get(i) >= data.get(i+1)){
                return false;
            }
        }

        return true;
    }

    private void fuzhu(TreeNode root, List<Integer> data){
        if(root==null){
            return;
        }

        fuzhu(root.left, data);
        data.add(root.val);
        fuzhu(root.right, data);
    }
}

代码---迭代上下限:

class Solution {
    public boolean isValidBST(TreeNode root) {
        return fuzhu(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    private boolean fuzhu(TreeNode root, long low, long up){
        // 如果是空节点,即正确 
        if(root==null){
            return true;
        }
        
        // 如果超出界限,则错误
        // 我们可以看出来,每次递归判断,只能判断一个节点,我们不可能一起判断左子和右子
        if(root.val <= low || root.val >= up){
            return false;
        }

        // 返回左子节点、右子节点的判断。
        return fuzhu(root.left, low, root.val) && fuzhu(root.right, root.val, up);
    }
}

以上内容即我想分享的关于力扣热题25的一些知识。

        我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1670953.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

讯方·智汇云校4月HCIE通过28人!证书量总计123!

智汇云校捷报 —4月华为认证证书量123本— 智汇云校4月IE捷报来了 讯方技术2024年PMP第一期3月考期顺利结班&#xff0c;考试全员通过~ 2024年4月&#xff0c;云校HCIA、HCIP、HCIE共通过123人&#xff01; 62人通过HCIA 33人通过HCIP 28人通过HCIE 祝贺以下学员通过HC…

基于Echarts的大数据可视化模板:服务器运营监控

目录 引言背景介绍研究现状与相关工作服务器运营监控技术综述服务器运营监控概述监控指标与数据采集可视化界面设计与实现数据存储与查询优化Echarts与大数据可视化Echarts库以及其在大数据可视化领域的应用优势开发过程和所选设计方案模板如何满足管理的特定需求模板功能与特性…

喜茶与 BE@RBRICK 联名,开启酷黑2.0全新潮流体验

5 月 13 日&#xff0c;喜茶官宣与知名潮玩 BERBRICK 联名&#xff0c;双方联合推出联名特调饮品「BERBRICK黑凤梨」、联名版 HEYTEA x BERBRICK 公仔套组&#xff0c;以及结合双方品牌元素全新设计的黑银视觉包材、周边、主题店氛围及线下活动等&#xff0c;带来全方位的酷黑潮…

Verilog中信号发生器的代码实现

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 描述 题目描述&#xff1a; 请编写一个信号发生器模块&#xff0c;根据波形选择信号wave_choise发出相应的波形&#xff1a;wave_choice0时&#xff0c;发出方波信号&#xff1b;wave_choice1时&#xff0c;发出锯齿…

【Java】Java中栈溢出的常见情况

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

ARM架构安全特性之隔离技术

安全之安全(security)博客目录导读 目录 一、保护代码和数据 二、TrustZone 三、安全世界之间的隔离 四、Secure-EL2扩展 五、保护主流计算工作负载 六、领域管理扩展(RME) 七、内存密集型可信应用程序 八、Arm动态TrustZone技术 强制执行明确定义的安全边界是安全工程…

maven .lastUpdated文件作用

现象 有时候我在用maven管理项目时会发现有些依赖报错&#xff0c;这时你可以看一下本地仓库中是否有.lastUpdated文件&#xff0c;也许与它有关。 原因 有这个文件就表示依赖下载过程中发生了错误导致依赖没成功下载&#xff0c;可能是网络原因&#xff0c;也有可能是远程…

韶音、南卡、倍思开放式耳机值得买吗?王牌机型对比测评

今年&#xff0c;开放式耳机市场迎来了众多新品&#xff0c;为消费者提供了丰富的选择。在这样的背景下&#xff0c;正确挑选一款既符合音质需求又兼具佩戴舒适的开放式耳机显得格外关键。作为长期使用开放式耳机的用户&#xff0c;我发现很多人在韶音、南卡、漫步者这三个品牌…

Linux-- 重定向缓冲区

目录 0.接上篇文章 1.粗略的见一下这两个问题 2.理解重定向 3.理解缓冲区 0.接上篇文章 Linux--基础IO&#xff08;文件描述符fd&#xff09;-CSDN博客 1.粗略的见一下这两个问题 先来了解几个函数&#xff1a; stat()函数用于获取指定文件或符号链接的元数据。如果文件是…

大数据BI可视化(Echarts组件)项目开发-熟悉结合Vue开发图表组件7.0附带1/6商家销售统计(横向柱状图)

一.创建项目 创建 1.npm install -g vue/cli vue create vision 2. 3. 4.版本 5.是否使用历史路由 6.CSS预处理 7.ES标准配置 8.啥时候es标准提示-保存文件后 9.将配置文件放入单独文件中处理 10.需要保留新建项目以上设置 11.选择“Use PNPM”或者“Use NPM” 12.创建 13访…

时间瑾眼中的IT行业现状与未来趋势

文章目录 技术革新与行业应用IT行业的人才培养与教育人工智能与机器学习的演进数据安全与隐私保护可持续发展与绿色技术社会责任与道德规范 随着技术的不断进步&#xff0c;IT行业已成为推动全球经济和社会发展的关键力量。从云计算、大数据、人工智能到物联网、5G通信和区块链…

AI 入门:AI 提示词如何入门?这篇就够了!(含提示词)

先看案例&#xff0c;一目了然 一个通用的提示词案例&#xff1a; 普通的提示词&#xff1a; 我给你我写的参考文章&#xff0c;请你学习我的风格来根据主题创作1篇文章。请你根据我给你的参考文章&#xff0c;学习我的写作风格&#xff0c;并进行风格学习模仿创作。为了更好…

python智能电力监控与资费电费缴纳管理系统vue+django

本系统的设计与实现共包含6个表:分别是配置文件信息表&#xff0c;电力记录信息表&#xff0c;故障报修信息表&#xff0c;缴费订单信息表&#xff0c;用户表信息表&#xff0c;用户信息表&#xff0c; 本文所设计的电费缴纳系统的设计与实现拥有前端和后端&#xff0c;前端使…

【声呐仿真】学习记录3.5-docker中Gazebo是否使用GPU?解决声呐图像黑屏

【声呐仿真】学习记录3.5-docker中Gazebo是否使用GPU&#xff1f;解决声呐图像黑屏 &#x1f921;打包镜像&#xff0c;重装驱动&#xff08;失败&#xff09;Xorg重新配置DAVE环境&#xff08;补充之前教程中的一些细节&#xff09;解决声呐图像黑屏问题 在容器中运行 roslau…

在ubuntu中使用python

在ubuntu中使用python ubuntu20版本中已经涵盖了python3&#xff0c;需要使用python3命令去运行 可以使用命令 python3 --version 进行检查 ubuntu20版本中已经涵盖了python3&#xff0c;需要使用python3命令去运行 可以使用命令 python3 --version 进行

基于STM32F401RET6智能锁项目(AT24C0X存储芯片)

一、IIC基本介绍 1、IIC通信接口 • I2C&#xff08;Inter IC Bus&#xff09;是由Philips公司开发的一种通用数据总线 • 两根通信线&#xff1a;SCL&#xff08;串行时钟线&#xff09;、SDA&#xff08;串行数据线&#xff09; • 同步&#xff0c;半双工 • 带数据应答 •…

长途火车~48小时记录

1.出门记得带大功率充电宝&#xff0c;最好是50000ma及以上的&#xff0c;不然还没上火车&#xff0c;手机就没电了&#xff0c;电量焦虑症又来了。手机有电就有无限可能。

家政服务新体验——家政小程序开发,让生活更轻松!

一、引言 随着现代生活节奏的加快&#xff0c;家政服务已经成为越来越多家庭不可或缺的一部分。然而&#xff0c;传统家政服务方式往往存在预约不便、服务质量参差不齐等问题。为了解决这些问题&#xff0c;我们精心打造了一款家政小程序&#xff0c;为您带来全新的家政服务体…

【送书福利第七期】你好!Java(文末送书)

文章目录 编辑推荐内容简介作者简介目录前言/序言 编辑推荐 适读人群 &#xff1a;程序员;相关院校师生 本书以轻松幽默的语言&#xff0c;从零开始介绍Java语言。书名来源于编程语言中最经典的Hello World程序&#xff0c;寓意带读者从入门到精通。 书中每章都设有总结与扩展…

绝地求生PUBG初版艾伦格回归 初版艾伦格和新版有什么区别

PUBG终于迎来了经典的旧版艾伦格地图的回归&#xff01;我们希望通过本次经典艾伦格的回归为大家带回记忆中那一幕幕熟悉的场景&#xff0c;并让大家好好回味一番当年与好友们共同冒险的峥嵘岁月&#xff01;还怀念从前为了抢到自己最爱的武器而飞奔的日日夜夜吗&#xff1f;那…