leecode/problems/98.validate-binary-search-tree.md
2020-05-22 18:17:19 +08:00

345 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 题目地址
https://leetcode.com/problems/validate-binary-search-tree/description/
## 题目描述
```
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
Example 1:
2
/ \
1 3
Input: [2,1,3]
Output: true
Example 2:
5
/ \
1 4
/ \
3 6
Input: [5,1,4,null,null,3,6]
Output: false
Explanation: The root node's value is 5 but its right child's value is 4.
```
## 思路
### 中序遍历
这道题是让你验证一棵树是否为二叉查找树BST。 由于中序遍历的性质`如果一个树遍历的结果是有序数组,那么他也是一个二叉查找树(BST)`,
我们只需要中序遍历然后两两判断是否有逆序的元素对即可如果有则不是BST否则即为一个BST。
### 定义法
根据定义,一个结点若是在根的左子树上,那它应该小于根结点的值而大于左子树最小值;若是在根的右子树上,那它应该大于根结点的值而小于右子树最大值。也就是说,每一个结点必须落在某个取值范围:
1. 根结点的取值范围为(考虑某个结点为最大或最小整数的情况):(long_min, long_max)
2. 左子树的取值范围为:(current_min, root.value)
3. 右子树的取值范围为:(root.value, current_max)
## 关键点解析
- 二叉树的基本操作(遍历)
- 中序遍历一个二叉查找树BST的结果是一个有序数组
- 如果一个树遍历的结果是有序数组,那么他也是一个二叉查找树(BST)
## 代码
### 中序遍历
* 语言支持JSC++, Java
JavaScript Code
```js
/*
* @lc app=leetcode id=98 lang=javascript
*
* [98] Validate Binary Search Tree
*/
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {boolean}
*/
var isValidBST = function(root) {
if (root === null) return true;
if (root.left === null && root.right === null) return true;
const stack = [root];
let cur = root;
let pre = null;
function insertAllLefts(cur) {
while(cur && cur.left) {
const l = cur.left;
stack.push(l);
cur = l;
}
}
insertAllLefts(cur);
while(cur = stack.pop()) {
if (pre && cur.val <= pre.val) return false;
const r = cur.right;
if (r) {
stack.push(r);
insertAllLefts(r);
}
pre = cur;
}
return true;
};
```
C++ Code
```c++
// 递归
class Solution {
public:
bool isValidBST(TreeNode* root) {
TreeNode* prev = nullptr;
return validateBstInorder(root, prev);
}
private:
bool validateBstInorder(TreeNode* root, TreeNode*& prev) {
if (root == nullptr) return true;
if (!validateBstInorder(root->left, prev)) return false;
if (prev != nullptr && prev->val >= root->val) return false;
prev = root;
return validateBstInorder(root->right, prev);
}
};
// 迭代
class Solution {
public:
bool isValidBST(TreeNode* root) {
auto s = vector<TreeNode*>();
TreeNode* prev = nullptr;
while (root != nullptr || !s.empty()) {
while (root != nullptr) {
s.push_back(root);
root = root->left;
}
root = s.back();
s.pop_back();
if (prev != nullptr && prev->val >= root->val) return false;
prev = root;
root = root->right;
}
return true;
}
};
```
Java Code:
```java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
Stack<Integer> stack = new Stack<> ();
TreeNode previous = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (previous != null && root.val <= previous.val ) return false;
previous = root;
root = root.right;
}
return true;
}
}
```
### 定义法
* 语言支持C++Python3, Java, JS
C++ Code
```C++
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
// 递归
class Solution {
public:
bool isValidBST(TreeNode* root) {
return helper(root, LONG_MIN, LONG_MAX);
}
private:
bool helper(const TreeNode* root, long min, long max) {
if (root == nullptr) return true;
if (root->val >= max || root->val <= min) return false;
return helper(root->left, min, root->val) && helper(root->right, root->val, max);
}
};
// 循环
class Solution {
public:
bool isValidBST(TreeNode* root) {
if (root == nullptr) return true;
auto ranges = queue<pair<long, long>>();
ranges.push(make_pair(LONG_MIN, LONG_MAX));
auto nodes = queue<const TreeNode*>();
nodes.push(root);
while (!nodes.empty()) {
auto sz = nodes.size();
for (auto i = 0; i < sz; ++i) {
auto range = ranges.front();
ranges.pop();
auto n = nodes.front();
nodes.pop();
if (n->val >= range.second || n->val <= range.first) {
return false;
}
if (n->left != nullptr) {
ranges.push(make_pair(range.first, n->val));
nodes.push(n->left);
}
if (n->right != nullptr) {
ranges.push(make_pair(n->val, range.second));
nodes.push(n->right);
}
}
}
return true;
}
};
```
Python Code:
```Python
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode, area: tuple=(-float('inf'), float('inf'))) -> bool:
"""思路如上面的分析用Python表达会非常直白
:param root TreeNode 节点
:param area tuple 取值区间
"""
if root is None:
return True
is_valid_left = root.left is None or\
(root.left.val < root.val and area[0] < root.left.val < area[1])
is_valid_right = root.right is None or\
(root.right.val > root.val and area[0] < root.right.val < area[1])
# 左右节点都符合,说明本节点符合要求
is_valid = is_valid_left and is_valid_right
# 递归下去
return is_valid\
and self.isValidBST(root.left, (area[0], root.val))\
and self.isValidBST(root.right, (root.val, area[1]))
```
Java Code:
```java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return helper(root, null, null);
}
private boolean helper(TreeNode root, Integer lower, Integer higher) {
if (root == null) return true;
if (lower != null && root.val <= lower) return false;
if (higher != null && root.val >= higher) return false;
if (!helper(root.left, lower, root.val)) return false;
if (!helper(root.right, root.val, higher)) return false;
return true;
}
}
```
JavaScript Code:
```javascript
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {boolean}
*/
var isValidBST = function (root) {
if (!root) return true;
return valid(root);
};
function valid(root, min = -Infinity, max = Infinity) {
if (!root) return true;
const val = root.val;
if (val <= min) return false;
if (val >= max) return false;
return valid(root.left, min, val) && valid(root.right, val, max)
}
```
## 相关题目
[230.kth-smallest-element-in-a-bst](./230.kth-smallest-element-in-a-bst.md)