booleanisValidBST(TreeNode root) {
if (root ==null) {
returntrue;
}
// false if left is > than rootif (root.left!=null&& root.left.val> root.val) {
returnfalse;
}
// false if right is<than rootif (root.right!=null&& root.right.val<root.val) {
returnfalse;
}
// false if, recursively, the left or right is not a BSTif (!isValidBST(root.left) ||!isValidBST(root.right)) {
returnfalse;
}
// passing all that, it's a BSTreturntrue;
}
1
2
3
4
graph TD;
A(3) --- B(2) & C(5)
B --- D(1) & E(4)
style E fill:orange
Method 1 - Recursive but Inefficient - Max Value and Min Value for Each Node#
For each node, check if max value in left subtree is smaller than the node and min value in right subtree greater than the node.
classSolution {
publicintisValidBST(TreeNode root) {
if (root ==null)
returntrue;
/* false if the max of the left is > than us */if (root.left!=null&& maxValue(root.left) > root.val) {
returnfalse;
}
/* false if the min of the right is <= than us */if (root.right!=null&& minValue(root.right) < root.val) {
returnfalse;
}
/* false if, recursively, the left or right is not a BST */if (!isValidBST(root.left) ||!isValidBST(root.right)) {
returnfalse;
}
/* passing all that, it's a BST */returntrue;
}
}
1
2
3
4
5
6
7
intminValue(TreeNode root) {
TreeNode current = root; // loop down to find the leftmost leafwhile (current.left!=null) {
current = current.left;
}
return (current.val);
}
1
2
3
4
5
6
7
intmaxValue(TreeNode root) {
TreeNode current = root; // loop down to find the leftmost leafwhile (current.right!=null) {
current = current.right;
}
return (current.val);
}
All values in the left subtree must be less than the root, and all values in the right subtree must be greater than the root. Therefore, we check each node’s value against these boundaries. This method traverses the left subtree first. If a violation occurs near the root but on the right subtree, the time complexity remains O(n). However, the second solution below can detect violations near the root more quickly.
classSolution {
publicbooleanisValidBST(TreeNode root) {
return helper(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
// We are using long min and long max to handle the case// when node's value is Integer.MIN_VALUE OR Integer.MAX_VALUEprivatebooleanhelper(TreeNode root, long min, long max) {
if (root ==null) {
returntrue;
}
if (root.val<= min && root.val>= max) {
returnfalse;
}
return helper(root.left, min, root.val) && helper(root.right, root.val, max));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution {
publicbooleanisValidBST(TreeNode root) {
return helper(root, null, null);
}
// We are using long min and long max to handle the case// when node's value is Integer.MIN_VALUE OR Integer.MAX_VALUEprivatebooleanhelper(TreeNode root, Integer min, Integer max) {
if (root ==null) {
returntrue;
}
return (min ==null|| root.val> min) && (max ==null|| root.val< max) && helper(root.left, min, root.val) && helper(root.right, root.val, max);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution {
publicbooleanisValidBST(TreeNode root) {
return helper(root, null, null);
}
// We are using long min and long max to handle the case// when node's value is Integer.MIN_VALUE OR Integer.MAX_VALUEprivatebooleanhelper(TreeNode root, TreeNode min, TreeNode max) {
if (root ==null) {
returntrue;
}
return (min ==null|| root.val> min.val) && (max ==null|| root.val< max.val) && helper(root.left, min, root) && helper(root.right, root, max);
}
}
Method 4 - Iterative Using Queue and Node Modification#
We can create a new BTNode with long left and right values, denoting the smallest value on the left and max value on right. Each time, we add value to queue, we set the min and max we have seen so far, and when we poll out the values should be in the range [left, right].
1
2
3
4
5
6
7
8
9
10
11
//define a BNode class with TreeNode and it's boundariesclassBNode {
TreeNode n;
long left;
long right;
publicBNode(TreeNode n, long left, long right) {
this.n= n;
this.left= left;
this.right= right;
}
}
Perform an in-order traversal of the tree and store the results in a temporary array.
Verify if the temporary array is sorted in ascending order; if so, the tree is a BST.
To avoid using an auxiliary array, we can track the previously visited node during the in-order traversal. If the current node’s value is less than the previous node’s value, the tree is not a BST.
The below code is just a modified version of the standard non-recursive Breadth First Search (BFS) of a binary tree. If you are unfamiliar with the algorithm for BFS, you can find Binary Tree Level Order Traversal.
To check if each node adheres to the rules of a binary search tree (BST), we verify that each left child’s value is less than the current node’s value and each right child’s value is greater. A binary tree is considered a BST if all nodes satisfy these conditions. If all nodes are validated without any violations, we return true; otherwise, we return false upon detecting a single violation.