Validate a BST
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Description
Given a binary search tree like the one below, can you write a function that will return true if it is valid?

5
/ \
3 9
/ \
1 4
Recall that a BST is valid only given the following conditions:
- The left child subtree of a node contains only nodes with values less than the parent node's.
- The right child subtree of a node contains only nodes with values greater than the parent node's.
- Both the left and right subtrees must also be BSTs.
You can assume that all nodes, including the root, fall under this node definition:
class Node {
constructor(val) {
this.value = val;
this.left = null;
this.right = null;
}
}
The method may be called like the following:
root = new Node(5);
root.left = new Node(3);
root.right = new Node(9);
console.log(isValidBST(root));
Constraints
- Length of the given tree <=
100000 - The nodes in the tree will always contain integer values between
-1000000000and1000000000 - Expected time complexity :
O(n) - Expected space complexity :
O(logn)orO(d)wheredis the depth of the tree
```js
function isValidBST(self, root) {
// Fill in this method
return self;
}
class Node {
constructor(val) {
this.value = val;
this.left = null;
this.right = null;
}
}
```
Multiple Choice
Which of the following is NOT a property of the Binary Search Tree data structure?
Order
Select the proper order of an in-order traversal for a Binary Search Tree:
Multiple Choice
A BST has integers as node keys. For an in-order traversal of a BST, in what order do the node keys get processed?
Multiple Choice
What would be the result of the following recursive function?
def func(num):
if n == 4:
return n
else:
return 2 * func(n+1);
func(2)
Fill In
The following is working code validating a Binary Search Tree in Python.
class Solution:
def is_valid_bst(self, root):
output = []
self.in_order(root, output)
for i in range(1, len(output)):
if output[i-1] >= output[i]:
return False
return True
def in_order(self, root, output):
if root is None:
return
____________________________________
output.append(root.val)
self.in_order(root.right, output)
Inputs And Outputs
Inputs and outputs
Let's start, as always, with a few examples. Running through some inputs helps our brains to intuit some patterns. This may help trigger an insight for a solution.
Let's say we just have this simple binary search tree:
```js
/*
5
/ \
3 9
*/
```
Brute Force Solution?
Is this valid? It sure seems so, the first criteria that comes to mind being that 3 is less than 5, and therefore that node is to the left. On the other hand, 9 is greater than 5, and thus is to the right. Alright, this seems like a no brainer, let's just check that every left child is smaller than the root, and every right child is greater than the local root.
Brute force solution?
Here's a possible early solution:
```js
function isValidBST(root) {
if (root.left < root.val && root.right > root.val) {
return true;
}
}
```
Step Nine
We should be able to run through that method recursively, and check every subtree. Is that enough though? Let's extend our tree a bit and add two more children to the root's left child.
```js
/*
5
/ \
3 9
/ \
2 8
*/
```
Pattern Recognition
Is the above a valid binary search tree? It is not -- if our root is 5, the entire left subtree (with 3 as the root) needs to have keys less than the parent tree's root key. Notice that the 8 is still to the left of 5, which is invalidates the simple recursive function from above.
Pattern recognition
In thinking about what we need to do with this tree, there clearly needs to be some form of traversal so that we can check the nodes against each other.
Two questions we can ask are: 1. Is there a way to compare node values without, or possibly exclusive, of the traversal? 2. What technique or pattern can help us easily compare tree values?
The answer is an in-order depth-first search of the tree. As you'll recall, an in-order DFS follows the standard depth-first method of going as deep as possible on each child before going to a sibling node. However, the difference is, it will process all left subtree nodes first, do something with the root or current node, and then process all right subtree nodes.
Because of the definition of a binary search tree, valid ones will produce an in-order DFS traversal in sorted order from least to greatest.
Thus, we can use this to our advantage. Here's a simple inOrder method to run through a binary search tree and return a list of node values.
```js
function inOrder(root, output) {
if (!root) {
return;
}
inOrder(root.left, output);
output.append(root.val);
inOrder(root.right, output);
}
```
Complexity Of Final Solution
If this is in sorted order, we know that this is valid. We can check this iterating through the returned list, checking that each iterated element's value is greater than the previous iteration's. If we get to the end, we can return True. If the opposite is ever true, we'll immediately return False.
Complexity of Final Solution
Let n be the size of the tree. We traverse through all n tree nodes using recursion for O(n) time complexity, and we have O(logn) space complexity due to recursion or O(d) where d is the depth of the tree.
One Pager Cheat Sheet
One Pager Cheat Sheet
- Write a function,
isValidBST(node), that returnstrueif the given binary search tree is valid according to the defined conditions. - The left subtree of a node in a Binary Search Tree (BST) must only contain nodes with keys LESS than the node's key, while the right subtree must contain nodes with keys GREATER than the node's key to maintain its in-order traversal which produces an increasing order of nodes.
- The In-order traversal of a Binary Search Tree follows a specific algorithm to access data in a very efficient manner, visiting each node left to right by recursively calling the
Inorder()function. - An in-order traversal of a
BSTprocesses the node keys in ascending order by beginning at the smallest key and progressively traversing rightward. - The given recursive function will
return2 times the result of the recursive call until the if statement evaluates toTrue, in which case thevalueofnisreturned, which in the example is4and the result offunc(2)is16. Running through inputs with a binary search tree can help trigger insights for a solution.-
Checking if every left child is smaller than the root, and every right child is greater than the local root is a
brute forcesolution for determining the direction of nodes in a tree. - We can
recursivelycheck every subtree by running through the method, but to ensure accuracy we should extend the tree by adding two more children to the root's left child. - We can use an
in-order depth-first searchto check abinary searchtree for validity by comparing its processed node values in sorted order. - We can determine if a given tree is valid in
O(n)time complexity andO(logn)space complexity by iterating through allnelements and checking that each successive element is greater than the previous iteration.