【每日一题】力扣98:验证二叉搜索树

136 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

题目

题目链接: 力扣98:验证二叉搜索树

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

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

  • 节点的左子树只包含 小于 当前节点的数。

  • 节点的右子树只包含 大于 当前节点的数。

  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

img

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

示例 2:

img

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

提示:

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

解题思路

思路一(纯中序遍历):

看到二叉搜索树首先应该想到的是中序遍历,二叉搜索树的中序遍历是递增的,所以这题可以用这种方法做。

中序遍历解法里面可以有个小优化:直接在遍历的过程判断是否存在先遍历的节点大于后遍历的节点。如果存在,直接返回false。否则,返回true。这时,就需要一个变量存储已经遍历的节点值,去和每个遍历的节点值比较。

有个要注意的地方是变量不能开 int,因为 Node.val 的取值范围是int的所有范围,如果用int,在判断前一个遍历过的节点值 f 的是否大于等于当前值 val 的时候会出错。val 可能等于 int 的最小值,这样就直接返回false了。所以 f 应该赋于初值小于int型的最小值:LONG_MIN。当然你也可以不用这种写法,用一个容器/数组存储一下,后面遍历是否递增即可。

思路二:

根据二叉搜索树的特点:节点的左子树的所有节点的值必须小于该结点的值,右子树必须大于。可以使用在二叉查找树(二叉搜索树)中查找的方法,一个分支一个分支进行查找,不过此题是验证是否是二叉搜索树,所以需要每个分支都遍历到。

简单的说就是利用该子树的最小值和最大值,判断该子树的所有节点值是否在这个范围内。

代码

思路一代码:

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        long long f = LONG_MIN;	//这里不能开int
        stack<TreeNode *> sta;
        while (!sta.empty() || root) {
            while (root) {
                sta.push(root);
                root = root->left;
            }
            TreeNode *p = sta.top();
            sta.pop();
            if (f >= p->val) {
                return false;
            }
            f = p->val;
            root = p->right;
        }
        return true;
    }
};
//中序遍历递归法太简单,省略。。。

思路二代码:

public:
    bool isture(TreeNode *root, long long min, long long max) {
        if (!root)
            return true;
        if (root->val <= min || root->val >= max)
            return false;
        return isture(root->left, min, root->val) && isture(root->right, root->val, max);
    }

    bool isValidBST(TreeNode* root) {
        return isture(root, LONG_MIN, LONG_MAX);
    }
};

总结

此题主要考二叉搜索树的性质:中序遍历递增和当前节点大于左子树,小于右子树。 利用中序遍历解题的思路一不难想到,但思路二相比思路一要难想一点。题目整体来说不难。对于每个类型的最大最小值宏定义变量最好记住,一些边界和比较问题可能会用上。