Medium!

题目描述:

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

一个二叉搜索树具有如下特征:

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

示例 1:

输入:
2
/ \
1 3
输出: true

示例 2:

输入:
5
/ \
1 4
  / \
  3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
  根节点的值为 5 ,但是其右子节点值为 4 。

解题思路:

这道验证二叉搜索树有很多种解法,可以利用它本身的性质来做,即左<根<右,也可以通过利用中序遍历结果为有序数列来做,下面我们先来看最简单的一种,就是利用其本身性质来做,初始化时带入系统最大值和最小值,在递归过程中换成它们自己的节点值,用long代替int就是为了包括int的边界条件,代码如下:

C++ 解法一:

// Recursion without inorder traversal
class Solution {
public:
bool isValidBST(TreeNode *root) {
return isValidBST(root, LONG_MIN, LONG_MAX);
}
bool isValidBST(TreeNode *root, long mn, long mx) {
if (!root) return true;
if (root->val <= mn || root->val >= mx) return false;
return isValidBST(root->left, mn, root->val) && isValidBST(root->right, root->val, mx);
}
};

这题实际上简化了难度,因为一般的二叉搜索树是左<=根<右,而这道题设定为左<根<右,那么就可以用中序遍历来做。因为如果不去掉左=根这个条件的话,那么下边两个数用中序遍历无法区分:

20       20
   /           \
 20           20

它们的中序遍历结果都一样,但是左边的是BST,右边的不是BST。去掉等号的条件则相当于去掉了这种限制条件。下面我们来看使用中序遍历来做,这种方法思路很直接,通过中序遍历将所有的节点值存到一个数组里,然后再来判断这个数组是不是有序的,代码如下:

C++ 解法二:

// Recursion
class Solution {
public:
bool isValidBST(TreeNode *root) {
if (!root) return true;
vector<int> vals;
inorder(root, vals);
for (int i = 0; i < vals.size() - 1; ++i) {
if (vals[i] >= vals[i + 1]) return false;
}
return true;
}
void inorder(TreeNode *root, vector<int> &vals) {
if (!root) return;
inorder(root->left, vals);
vals.push_back(root->val);
inorder(root->right, vals);
}
};

下面这种解法跟上面那个很类似,都是用递归的中序遍历,但不同之处是不将遍历结果存入一个数组遍历完成再比较,而是每当遍历到一个新节点时和其上一个节点比较,如果不大于上一个节点那么则返回false,全部遍历完成后返回true。代码如下:

C++ 解法三:

// Still recursion
class Solution {
public:
TreeNode *pre;
bool isValidBST(TreeNode *root) {
int res = 1;
pre = NULL;
inorder(root, res);
if (res == 1) return true;
else false;
}
void inorder(TreeNode *root, int &res) {
if (!root) return;
inorder(root->left, res);
if (!pre) pre = root;
else {
if (root->val <= pre->val) res = 0;
pre = root;
}
inorder(root->right, res);
}
};

当然这道题也可以用非递归来做,需要用到栈,因为中序遍历可以非递归来实现,所以只要在其上面稍加改动便可,代码如下:

C++ 解法四:

// Non-recursion with stack
class Solution {
public:
bool isValidBST(TreeNode* root) {
stack<TreeNode*> s;
TreeNode *p = root, *pre = NULL;
while (p || !s.empty()) {
while (p) {
s.push(p);
p = p->left;
}
TreeNode *t = s.top(); s.pop();
if (pre && t->val <= pre->val) return false;
pre = t;
p = t->right;
}
return true;
}
};

最后还有一种方法,由于中序遍历还有非递归且无栈的实现方法,称之为Morris遍历,可以参考http://www.cnblogs.com/grandyang/p/4297300.html,这种实现方法虽然写起来比递归版本要复杂的多,但是好处在于是O(1)空间复杂度,参见代码如下:

C++ 解法五:

class Solution {
public:
bool isValidBST(TreeNode *root) {
if (!root) return true;
TreeNode *cur = root, *pre, *parent = NULL;
bool res = true;
while (cur) {
if (!cur->left) {
if (parent && parent->val >= cur->val) res = false;
parent = cur;
cur = cur->right;
} else {
pre = cur->left;
while (pre->right && pre->right != cur) pre = pre->right;
if (!pre->right) {
pre->right = cur;
cur = cur->left;
} else {
pre->right = NULL;
if (parent->val >= cur->val) res = false;
parent = cur;
cur = cur->right;
}
}
}
return res;
}
};

LeetCode(98): 验证二叉搜索树的更多相关文章

  1. LeetCode 98. 验证二叉搜索树 | Python

    98. 验证二叉搜索树 题目来源:https://leetcode-cn.com/problems/validate-binary-search-tree 题目 给定一个二叉树,判断其是否是一个有效的 ...

  2. Java实现 LeetCode 98 验证二叉搜索树

    98. 验证二叉搜索树 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右 ...

  3. 力扣Leetcode 98. 验证二叉搜索树

    验证二叉搜索树 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身 ...

  4. LeetCode 98 验证二叉搜索树

    题目: 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是 ...

  5. Leetcode 98 验证二叉搜索树 Python实现

    给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是二叉搜索 ...

  6. LeetCode 98——验证二叉搜索树

    1. 题目 2. 解答 2.1. 方法一 我们初始化根节点的范围为长整形数据的最小最大值 \([LONG\_MIN,LONG\_MAX]\),则其左子节点的取值范围为 \([LONG\_MIN,根节点 ...

  7. LeetCode 98. 验证二叉搜索树(Validate Binary Search Tree)

    题目描述 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也 ...

  8. LeetCode:验证二叉搜索树【98】

    LeetCode:验证二叉搜索树[98] 题目描述 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当 ...

  9. 【LeetCode】98. 验证二叉搜索树

    98. 验证二叉搜索树 知识点:二叉树:递归 题目描述 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大 ...

  10. 98. 验证二叉搜索树 前序遍历解法以及后续遍历解法(go语言)

    leetcode题目 98. 验证二叉搜索树 前序遍历 最简洁的答案版本,由于先判断的是根节点,所以直接判断当前root的值v,是否满足大于左子树最大,小于右子树最小,然后再遍历左子树,右子树是否是这 ...

随机推荐

  1. 【网络爬虫入门03】爬虫解析利器beautifulSoup模块的基本应用

    [网络爬虫入门03]爬虫解析利器beautifulSoup模块的基本应用   1.引言 网络爬虫最终的目的就是过滤选取网络信息,因此最重要的就是解析器了,其性能的优劣直接决定这网络爬虫的速度和效率.B ...

  2. linux 僵屍进程

    参考链接 :  http://soft.chinabyte.com/os/5/12172005.shtml

  3. 【blog】Hibernate5如何设置SQLite的方言(待更新...)

    参考链接 Hibernate3.Hibernate4.Hibernate5 hibernate5连接sqlite (目前参考的是这个方法)

  4. 使用AOP思想无侵入式申请权限,解决组件化中权限问题(一)

    首先介绍AspectJx使用 https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx 在根项目的build.gradle ...

  5. Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客

    ==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...

  6. 2017-2018-2 20165234 实验三 《Java面向对象程序设计》实验报告

    实验三 敏捷开发与XP实践 http://www.cnblogs.com/rocedu/p/4795776.html, Eclipse的内容替换成IDEA 参考 http://www.cnblogs. ...

  7. 关于iframe的相关操作

    1.判断当前页面是否在iframe当中 if (top.location != self.location) { alert("in iframe") }

  8. 快速开发工具:Servoy

    快速开发工具:Servoy https://servoy.com/

  9. Webpack2 中的 NamedModulesPlugin 与 HashedModuleIdsPlugin

    要讨论Webpack 2中新增的这两个plugin的功能,还要先从使用Webpack打包的项目的前端资源缓存方案说起. 通常在使用了Webpack的项目中我们会使用CommonsChunkPlugin ...

  10. Liunx之始

    作者:邓聪聪 本章是为了工作之需要,所做的一个学习心得,也为自己留下相关印记以便日后留用. 1:安装服务yum install ppp -yyum install pptpd -y由于yum源没有pp ...