当前位置: 首页 > news >正文

【leetcode】98.验证二叉搜索树

文章目录

  • 碎碎念
  • 一、题目
  • 二、思路和题解
    • 1.思路
    • 2.代码(递归)
  • 三、其他解法(中序遍历+判断升序)
    • 1.思路
    • 2.代码
  • 四、错误回顾

碎碎念

好!好久没刷leetcode了,欠了好多个题解没给自己补上我有罪…以至于现在好多都忘记了当时怎么做的以及有啥问题…我接下来一定及时写啊啊啊啊!
好累好累啊啊啊最近!忙完你的忙你的忙完你的忙你的…看的眼睛酸酸累累的。不管了,既然这篇开坑了就写完它!


一、题目


二、思路和题解

1.思路

难死我了呃呃呃呃呃
做二叉树相关的题目第一反应还是递归了,但由于苯人对二叉搜索树(BST,Binary Search Tree)的概念还是把握的不是很清晰啊于是只考虑一层的:左节点值小于根节点值,右节点值大于根节点值。一旦出现错的就返回false,没有就继续递归左子树和右子树,直到找到最后都没有false就可以返回true了。

但是!!二叉搜索树不是这样的!二叉搜索树要求左子树的所有节点的值都要小于根节点的值,右子树的所有节点的值也要大于根节点的值。所!以!咱们需要用新的min_nodemax_node变量来存储当前的上界和下界(所以就要引入辅助函数啦),也就是这个节点在什么样一个范围里才是合法的,如果不在这个范围,那就直接false。

举个合法的二叉搜索树的例子,这里我按照层序来一个个讲:

5 (根节点) / \ 3 7 (3是左子树,7是右子树) / \ / \ 2 4 6 8 (叶子节点)
  • 最开始的时候根节点的取值是没有限制的,因此它没有上界和下界;
  • 到3这个节点时,按BST的规则,这个节点必须小于父节点的值,所以上界是5,下界依旧没有;
  • 到7这个节点时,按BST的规则,这个节点必须大于父节点的值,所以下界是5,上界依旧没有;
  • 再往下,到2这个节点时,上界是3,下界没有;
  • 到4这个节点就要注意了,它在3的右子树,所以下界是3,但它同时也在5的左子树,所以上界是5
  • 到6节点,一样的,它在7的左子树,所以上界是7,同时它也在5的右子树,所以下界是5
  • 8这个节点在7的右子树,也在5的右子树,所以下界是5和7,取大的,下界是7。

很显然的,每个节点的值都是在合法的范围的,因此这就是一个合法的BST。

这里的上下界我们手工是看的明白的,但在代码里,就需要“继承”一下啦,我们直接看代码!(建议跟着代码走一遍~)

2.代码(递归)

/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), * right(right) {} * }; */classSolution{public:// 辅助函数,可以“继承”上下界的值,也可以判断是否在范围内boolcheckBST(TreeNode*root,TreeNode*min_node,TreeNode*max_node){// 边界条件if(root==nullptr){returntrue;}// 如果超出下界,不合法if(min_node!=nullptr&&root->val<=min_node->val){returnfalse;}// 如果超出上界,不合法if(max_node!=nullptr&&root->val>=max_node->val){returnfalse;}// 需要接收递归传回来的值,然后查看左右子树是否都合法// 注意这里左节点的下界是继承的,上界更新;右节点的上界是继承的,下界更新returncheckBST(root->left,min_node,root)&&checkBST(root->right,root,max_node);}boolisValidBST(TreeNode*root){// 初始状态上界和下界都是nullreturncheckBST(root,nullptr,nullptr);}};
  • 时间复杂度:O(n)
    算法会访问每一个节点恰好一次
  • 空间复杂度:O(h)(h是树的高度)
    递归的空间开销来自「函数调用栈」(系统为每个递归调用保存上下文),栈的深度等于递归的最大深度(即树的高度 h)

三、其他解法(中序遍历+判断升序)

1.思路

BST的特点是中序遍历的话是升序的!!

利用这个特点就可以美美解决了,只要不是升序的就是false。

中序遍历请看:【leetcode】94.二叉树的中序遍历(含前序、后序遍历相关内容)

这里我就用的栈模拟了。

2.代码

/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), * right(right) {} * }; */classSolution{public:// 中序遍历+升序判断boolisValidBST(TreeNode*root){vector<int>res;// 存储遍历结果stack<TreeNode*>st;// 辅助栈TreeNode*cur=root;// 游标指针,从根节点开始// 循环条件:cur非空或栈非空(两者都空说明遍历完成)while(cur!=nullptr||!st.empty()){// 把当前节点的所有左孩子依次入栈if(cur!=nullptr){st.push(cur);cur=cur->left;}else{// 栈顶出栈,访问根节点(加入结果)cur=st.top();st.pop();res.push_back(cur->val);// 处理右子树,游标指向右孩子cur=cur->right;}}//判断是否升序for(inti=0;i<res.size()-1;i++){if(res[i]>=res[i+1]){returnfalse;}}returntrue;}};
  • 时间复杂度O(n)
    中序遍历访问每个节点一次,每个节点的入栈 / 出栈操作是 O(1) → 遍历时间 O(n);
    序列检查遍历 vector 中的 n 个元素,每个元素的比较操作是 O(1) → 检查时间 O(n);
    总时间 = 遍历 O(n) + 检查 O(n) = O(2n) → O(n)。
  • 空间复杂度O(n)
    存储中序序列的 vector res:需要保存 n 个节点值 → 空间 O(n);
    辅助栈 stack<TreeNode*> st:栈的最大大小等于树的高度 h(和递归栈类似)→ 空间 O(h);
    总空间 = O(n) + O(h) → 因为 h ≤ n,所以最终空间复杂度 O(n)(主导项是 vector 的 O(n))

四、错误回顾

1.对BST概念和特点不熟悉,思路上有漏洞,只考虑了一层
2.树的一些基本语法也是手太生了哈,居然都写成root->left.val了…(正确是root->left->val!!!)

http://www.cnnetsun.cn/news/1315699.html

相关文章:

  • 给我的 QQ 助理换个“最强大脑”:Windows 部署 OpenClaw + 替换模型攻略
  • 精益生产常见误区,90%的企业都踩过坑?
  • 用户态网络缓冲区设计
  • Linux学习笔记1
  • 在matlab上进行基于深度强化学习算法自适应调节PID参数的控制,实现一级倒立摆的起摆和平衡
  • Matlab Simulink下的LLC并网与离网逆变器功能介绍:电流闭环控制并网,电压电流双...
  • 微信官方分账开通对接(技术+流程)指南+第三方分账系统科普
  • 基于GD32F303的便携式教学数字示波器设计
  • Ostrakon-VL-8B实战案例:识别店铺名/厨房违规/货架缺货——零售场景79类细粒度任务演示
  • SENT信号解码实战——从半字节到完整帧的解析指南
  • 立创开源:基于ASRPro与ESP8266的离线智能语音盒子设计与实现
  • Linux系统下Qwen3-TTS的部署与优化
  • Qwen3-ASR-1.7B应用场景:跨境电商客服语音质检系统落地
  • QT 消息提示框的优雅退场:定时关闭与透明度渐变动效实现
  • 从零开始:使用Kettle 9.x实现Hadoop数据导入导出完整流程
  • YOLO-v8.3常见问题:镜像使用中的疑难解答与技巧分享
  • Alibaba DASD-4B Thinking 对话工具在软件测试中的应用:自动化生成测试用例与对话脚本
  • Windows下用Python脚本批量下载ECMWF ERA5-Land数据的完整指南(含API配置避坑)
  • Kimi-VL-A3B-Thinking多模态应用:工业检测缺陷图→定位+分类+原因推测三级响应
  • 基于Qwen3-ASR-1.7B的智能会议记录系统开发实战
  • STC32G12K128开发板驱动1.8寸ST7735屏实战:基于天问Block图形化编程实现RTC数字时钟
  • JSP+Servlet开发避坑指南:从参数传递到会话管理,这些细节你注意了吗?
  • Human3.6M数据集实战:从申请到预处理的全链路指南
  • 履带四足复合机器人硬件设计与嵌入式实现
  • DeOldify在运维监控领域的应用:为黑白日志图表与拓扑图自动上色
  • PROJECT MOGFACE编程助手实战:辅助完成C语言基础代码编写与调试
  • 拆解微型逆变器:为什么GaN+Cyclo拓扑是未来趋势?(实测数据)
  • 基于模型预测算法的含储能微网双层能量管理模型探索
  • 6大厂商对比指南:2026CRM系统全链路数字化能力盘点
  • 新手入门:小数锁相环与整数锁相环教程