第37期:从头学二叉搜索树(面试常考)
时间:2022-07-25
本文章向大家介绍第37期:从头学二叉搜索树(面试常考),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
在上一节中,我们分别学习了DFS与BFS。在本节中,我们将继续学习一种特殊的二叉树结构 —— 二叉搜索树(BST)。
01、二叉搜索树
先看定义:二叉搜索树(Binary Search Tree),(又:二叉查找树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。
这里强调一下子树的概念:设T是有根树,a是T中的一个顶点,由a以及a的所有后裔(后代) 导出的子图称为有向树T的子树。具体来说,子树就是树的其中一个节点以及其下面的所有的节点所构成的树。
比如下面这就是一颗二叉搜索树:
下面这两个都不是:
图中 4 节点位置的数值应该大于根节点
图中 3 节点位置的数值应该大于根节点
那我们如何来验证一颗二叉搜索树?我们看题。
02、题目分析
第98题:验证二叉搜索树 |
---|
给定一个二叉树,判断其是否是一个有效的二叉搜索树。 |
示例 1:
输入:
5
/
1 4
/
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
示例 2:
输入:
5
/
1 4
/
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
首先看完题目,我们很容易想到 遍历整棵树,比较所有节点,通过 左节点值<节点值,右节点值>节点值 的方式来进行求解。但是这种解法是错误的,因为对于任意一个节点,我们不光需要左节点值小于该节点,并且左子树上的所有节点值都需要小于该节点。(右节点一致)所以我们在此引入上界与下界,用以保存之前的节点中出现的最大值与最小值。
03、递归求解
明确了题目,我们直接使用递归进行求解。这里需要强调的是,在每次递归中,我们除了进行左右节点的校验,还需要与上下界进行判断。由于该递归分析有一定难度,所以我们先展示代码:
func isValidBST(root *TreeNode) bool {
if root == nil{
return true
}
return isBST(root,math.MinInt64,math.MaxInt64)
}
func isBST(root *TreeNode,min, max int) bool{
if root == nil{
return true
}
if min >= root.Val || max <= root.Val{
return false
}
return isBST(root.Left,min,root.Val) && isBST(root.Right,root.Val,max)
}
运行结果:
如果觉得上文中的递归不太容易理解,可以通过下图理解:
- 浣熊检测器实例, 如何用TensorFlow的Object Detector API来训练你的物体检测器
- 用Keras进行深度学习模式的正则化方法:Dropout
- 用深度学习硬件的闲置时间,来挖比特币
- 深度学习:如何理解tensorflow文本蕴含的原理
- 重磅!腾讯与科大讯飞技术共创,Google ProtoBuf进入TARS家族!
- 深度学习与R语言
- 在Keras中展示深度学习模式的训练历史记录
- 分析漏洞利用工具包 Archie和Astrum工具包
- 手游热更新方案xLua开源:Unity3D下Lua编程解决方案
- 如何为Keras中的深度学习模型建立Checkpoint
- Dubbo 源码解析 —— Zookeeper 创建节点
- 熔断器 Hystrix 源码解析 —— 断路器 HystrixCircuitBreaker
- 源码级别解读 mybatis 插件
- 在WebKit中并行加载外部脚本译:
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法