2021.10.8 力扣-验证二叉搜索树

题目描述:

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

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

节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

方法一(自己写的递归):

/**
 * 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) {}
 * };
 */
 class Solution {
 public:
     bool flag = true;
     //pair的第一个数存放当前以root为根的子树中的最小值,第二个数存放子树中的最大值
     pair<int, int> isvalid(TreeNode* root)             
     {
         pair<int, int> root_p(root->val, root->val);
         //如果存在左子树,就递归进入左子树
         if (root->left != nullptr)                     
         {
             pair<int, int> left_p = isvalid(root->left);
             //如果root的值大于左子树的最大值,说明没问题,更新root_p的first
             if (root->val > left_p.second)
             {
                 root_p.first = min(root_p.first, left_p.first);
             }
             //否则说明不是一个有效的二叉搜索树
             else flag = false;
         }
         //如果存在右子树,就递归进入右子树
         if (root->right != nullptr)
         {
             pair<int, int> right_p = isvalid(root->right);
             //如果root的值小于于右子树的最小值,说明没问题,更新root_p的second
             if (root->val < right_p.first)
             {
                 root_p.second = max(root_p.second, right_p.second);
             }
             //否则说明不是一个有效的二叉搜索树
             else flag = false;
         }
         return root_p;
     }
     bool isValidBST(TreeNode* root) {
         if (root == nullptr) return true;
         isvalid(root);
         return flag;
      }
 };

我的思路是每次递归返回这个子树的最大值和最小值,然后判断根的值是否大于左子树中的最大值和小于右子树中的最小值,由于需要用到字数的最大值和最小值,所以返回类型用到了pair,而作为判断的flag只能设在函数外面了。

但这样做效率并不高,我总觉得写的也有点怪怪的,看看其他人有没有更好的做法吧。

方法二(官方题解的递归):

/**
 * 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) {}
 * };
 */
 class Solution {
 public:
     bool isvalid(TreeNode* root, long long low, long long up)             
     {
         if (root == nullptr) return true;
         //如果不在(low,up)这个区间内,说明不是有效的二叉搜索树
         if (root->val <= low || root->val >= up)
         {
             return false;
         }
         return isvalid(root->left, low, root->val) && isvalid(root->right, root->val, up);
     }
     bool isValidBST(TreeNode* root) {
         return isvalid(root, LONG_MIN, LONG_MAX);
      }
 };

官方的递归题解,果然是优美简洁又高效,思路就是每次递归判断当前节点的值是否在(low,up)这个开区间内,不是就说明不是有效的二叉搜索树。

不过一开始看到这个方法的时候想了个问题挺久:较深层处的节点的值能保证和高层处的节点也满足二叉搜索树的定义吗?例如下图:

假设a是根节点,那么从上往下,若b>a,d>b,c<b,但是如果c小于a的话能判断出来吗?

是没问题的,只要在a和c之间的节点都满足二叉搜索树的定义的话,那么a和c之间的节点肯定都是大于a的,所以当遍历到节点c时,区间的左边界肯定不会比a小,因此若c小于a肯定能够判断出来。

 方法三(中序遍历递归):

/**
 * 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) {}
 * };
 */
 class Solution {
 public:
     long long num = LONG_MIN;
     bool isValidBST(TreeNode* root) {
         if (root == nullptr) return true;
         if (!isValidBST(root->left)) return false;
         if (root->val <= num) return false;
         num = root->val;
         return isValidBST(root->right);
      }
 };

看了这句话:“中序遍历为升序”,突然间豁然开朗,中序遍历是个先访问左节点、再访问根节点、最后访问右节点的过程,对应二叉搜索树的话,不就是从小到大升序吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值