题目描述
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
方法思路
Approach1: recursive + inorder traversal
Compute inorder traversal list inorder.
Check if each element in inorder is smaller than the next one.
class Solution{
//Runtime: 1 ms, faster than 39.94%
//Memory Usage: 38.5 MB, less than 47.99%
List<Integer> list;
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
list = new ArrayList<>();
validHelper(root);
for(int i = 0; i < list.size() - 1; i++)
if(list.get(i) >= list.get(i + 1))
return false;
return true;
}
public void validHelper(TreeNode root){
if(root == null) return;
validHelper(root.left);
list.add(root.val);
validHelper(root.right);
return;
}
}
Approach2: 方法一的非递归实现
Do we need to keep the whole inorder traversal list?
Actually, no. The last added inorder element is enough to ensure at each step that the tree is BST (or not). Hence one could merge both steps into one and reduce the used space.
class Solution {
//Memory Usage: 40.3 MB, less than 5.22%
//Runtime: 2 ms, faster than 24.92%
public boolean isValidBST(TreeNode root) {
Stack<TreeNode> stack = new Stack();
double inorder = - Double.MAX_VALUE;
while (!stack.isEmpty() || root != null) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
// If next element in inorder traversal
// is smaller than the previous one
// that's not BST.
if (root.val <= inorder) return false;
inorder = root.val;
root = root.right;
}
return true;
}
}
Approach3: recursive (觉得是很乱的方法却又是效率最高的)tricky
The idea above could be implemented as a recursion. One compares the node value with its upper and lower limits if they are available. Then one repeats the same step recursively for left and right subtrees.
class Solution {
//Runtime: 0 ms, faster than 100.00%
//Memory Usage: 38.2 MB, less than 71.81%
public boolean isBSTHelper
(TreeNode node, Integer lower_limit, Integer upper_limit) {
if ((lower_limit != null) && (node.val <= lower_limit))
return false;
if ((upper_limit != null) && (upper_limit <= node.val))
return false;
boolean left =
node.left != null ? isBSTHelper(node.left, lower_limit, node.val) : true;
if (left) {
boolean right =
node.right != null ? isBSTHelper(node.right, node.val, upper_limit) : true;
return right;
} else
return false;
}
public boolean isValidBST(TreeNode root) {
if (root == null)
return true;
return isBSTHelper(root, null, null);
}
}
Approach4:方法三的非递归实现
The above recursion could be converted into iteration, with the help of stack. DFS would be better than BFS since it works faster here.
class Solution {
//Runtime: 2 ms, faster than 24.92%
//Memory Usage: 40.4 MB, less than 5.01%
public boolean isValidBST(TreeNode root) {
if (root == null)
return true;
LinkedList<TreeNode> stack = new LinkedList();
LinkedList<Integer> upper_limits = new LinkedList();
LinkedList<Integer> lower_limits = new LinkedList();
stack.add(root);
upper_limits.add(null);
lower_limits.add(null);
while (!stack.isEmpty()) {
TreeNode node = stack.poll();
Integer lower_limit = lower_limits.poll();
Integer upper_limit = upper_limits.poll();
if (node.right != null) {
if (node.right.val > node.val) {
if ((upper_limit != null) && (node.right.val >= upper_limit))
return false;
stack.add(node.right);
lower_limits.add(node.val);
upper_limits.add(upper_limit);
} else
return false;
}
if (node.left != null) {
if (node.left.val < node.val) {
if ((lower_limit != null) && (node.left.val <= lower_limit))
return false;
stack.add(node.left);
lower_limits.add(lower_limit);
upper_limits.add(node.val);
} else
return false;
}
}
return true;
}
}