Leetcode 98. 验证二叉搜索树

心路历程:

第一反映就是递归判断每个子树是否root的值大于左结点小于右节点的值,然后不断递归。后来写完之后发现错了,题目中不仅要求当前结点,还得保证其子树内的所有元素都得满足和root的大小关系。

然后想着这下麻烦了,需要记录一些值,不能单纯的遍历考虑一层的事情了。因为需要同时考虑一个root的左右子树的最大值和最小值,所以将递归函数返回值设置为:是否是二叉搜索树,该树的最大值,该树的最小值(包含自己)。这样就可以做了。

再次印证二叉树问题递归函数输入基本就是结点,return是比较多样的。

后面看了代码随想录的解法,发现'中序遍历下,输出的二叉搜索树节点的数值是有序序列。有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。'

后来发现用中序遍历这道题会好做很多,需要记录前一个结点的值。其实这个也是用到了中序遍历顺序就是数组上升序列这一特性。

注意的点:

1、只需要返回当前root下树的最大值,最小值,不需要按照左子树最大最小值,右子树最大最小值来思考。需要维护循环不变量。

2、函数传参不要传反了

3、叶子节点可以用正负无穷来表示,这样更新的时候min max就能去掉了

4、二叉树问题需要深刻理解四种遍历的意义

5、如果找不到中序遍历这种特性的话,就会麻烦一点。

解法一:递归遍历 后序

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:

        # 二叉树一个简单的地方就在于递归函数传参只考虑节点即可,后序遍历
        # 注意需要保证根节点大于或者小于子树中所有的数
        # 返回值: 是否是二叉搜索树,该树下面的最大值,该树下面的最小值(包含自己)
        # 这道题属于记录最值就可以,如果需要记录所有的节点值,那么就有点类似回溯算法需要在维护一个全局变量
        def dfs(node):
            if not node:
                return True, -float('inf'), float('inf')
            
            l1, l2, l3 = dfs(node.left)
            r1, r2, r3 = dfs(node.right)

            # 先看是不是二叉搜索树
            flag = True
            if node.right:
                if node.val >= r3:
                    flag = False
            if node.left:
                if node.val <= l2:
                    flag = False
            
            # 再更新最大值,最小值
            max_value = max(node.val, l2, r2)
            min_value = min(node.val, l3, r3)
            
            return flag and l1 and r1 , max_value, min_value  # 参数传反了!!!
        
        res, _, _ = dfs(root)
        return res

解法二:中序遍历验证是否上升

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.vec = []

    def traversal(self, root):
        if root is None:
            return
        self.traversal(root.left)
        self.vec.append(root.val)  # 将二叉搜索树转换为有序数组
        self.traversal(root.right)

    def isValidBST(self, root):
        self.vec = []  # 清空数组
        self.traversal(root)
        for i in range(1, len(self.vec)):
            # 注意要小于等于,搜索树里不能有相同元素
            if self.vec[i] <= self.vec[i - 1]:
                return False
        return True
相关推荐
银-豆豆14 分钟前
数据结构与算法-动态规划、回溯与贪心
算法·动态规划
想吃火锅10052 小时前
【leetcode】200. 岛屿数量
算法·leetcode·职场和发展
Nil2083 小时前
leetcode 54螺旋矩阵
算法·leetcode·矩阵
依然鸣3 小时前
PTA团体程序设计天梯赛L1真题讲解L1-077-080
开发语言·c++·算法·深度优先·pat考试·图论
qeen876 小时前
【数据结构】自平衡二叉搜索树各种旋转算法原理解析及AVL树的C++实现
数据结构·c++·算法
lucas_AI6 小时前
1.2B 小模型赢过 235B 大模型:NaviDC-OCR 把文档解析卷明白了
人工智能·深度学习·算法
冻柠檬飞冰走茶7 小时前
PTA基础编程题目集 7-35有理数均值(C++语言实现)
开发语言·数据结构·c++·算法·均值算法
民乐团扒谱机7 小时前
【微实验】倒谱算法(Cepstrum)深度解析:原理、数学推导与代码实现
人工智能·算法·语音识别
evans在进步8 小时前
LeetCode 394:字符串解码——Java 单栈模拟与嵌套解析详解
java·python·leetcode
Nil2088 小时前
leetcode 189轮转数组
数据结构·算法·leetcode