LeetCode验证二叉搜索树
给你一个二叉树的根节点 root
,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:root = [2,1,3]
输出:true
示例 2:
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。
思路:
通过这道题我们正好可以复习一下二叉搜索树的定义。根据题目中给的二叉搜索树性质,对于任何一个节点,它都要满足一定的左右子树之间的关系——那我们必然要通过递归的方式去验证。
但这里就涉及到一个非常容易错的递归方式:对于每一个节点,它的左节点小于它,它的右节点大于它。这样写是错误的。因为这样只满足了对于每一个节点下的局部条件。比如对于这样的情况:
假设3还有一个左节点,值为1,显然这种情况下节点1没有大于2,不满足“某一节点的整个右子树全部大于它”,不是一棵二叉搜索树。但按照我们的错误递归是符合条件的,我们就把它当成了一棵二叉搜索树。
因此我们要换一个思路,不能“向下写条件”——而是“向上”去写:对于每一个节点,我们只需要看这个节点自己的值是不是符合条件就行(看它是否大于它的左根节点,或者小于它的右根节点)。这样我们把每一个节点的值都判断到位,不会出现误判情况。
这样的递归实现方式也很简单,我们给递归函数增加额外两个参数:这个节点不能超过的值和不能小于的值。起初对于根节点,对他的范围没有要求,则初始化为正负无穷。对于某个节点A的左子节点B,则B不能超过的值就是A;其余同理。
代码:
class Solution(object):
def isValidBST(self, root):
def is_valid(root,minn,maxx):#定义递归函数,添加额外两个参数
#base case:一直到最后都没有返回False,则返回True
if not root:return True
if root.val>=maxx or root.val<=minn:#有任何一个条件不满足
return False#不是二叉搜索树
#如果当前节点初步满足条件,继续判定它的左右子节点情况
#注意要把它的值传给递归函数is_valid作为相应的限定
left_is = is_valid(root.left,minn,root.val)#判断左边的是否满足
right_is = is_valid(root.right,root.val,maxx)#判断右边的是否满足
if left_is and right_is:#如果左右都ok则ok
return True
return False #否则不ok
return is_valid(root,float('-inf'),float('inf'))
小结:
这道题要注意的点就是不要写成错误的递归形式。然后记住正确形式应该添加两个参数作判断范围用。从正确的递归代码来看,我们也不需要跳进递归中去,这个递归函数的功能是很明确的:传入一个二叉树的根节点,返回这个二叉树是否是二叉搜索树。
其具体实现也可以从自身单层定义中实现自洽:对于每一个节点,首先它自身满足条件范围,其次判断其左右子节点是否也满足条件,若都满足,则这个以这个节点作为根节点的二叉树就是一棵二叉搜索树。
可以发现,一个正确的递归函数,1.有着明确的功能定义(传入的是什么,得到的是什么)。2.在函数体内部单层(不需要再跳进下一层递归)就可以完美实现逻辑闭合得到结果。这就是递归之美~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了