This is one of the most asked coding interview problems related to Binary Tre, at the top tech companies like Amazon, Google, Microsoft, Dunzo, etc. In this article we’ve tried our best to incorporate everything that one needs to know about this subject. So to get your queries answered, stay tuned till the end of this blog.
Introduction
To find the largest BST in a binary tree we should be aware of the following terms:
Binary Tree: A binary tree is defined as a tree with no more than two children. Each binary tree element can only have two children, we call them the left and right child.
Binary Search Tree: A binary search tree is a data structure that allows us to keep a sorted list of numbers in a short amount of time. A binary Search tree is also called a binary tree because each BST tree node has a maximum of two children. It is also called a search tree because this can be used to search for the presence of a number in logarithmic time. There are some properties that separate a normal binary tree from BST like All nodes of the left subtree are less than the root node in Bst and all the nodes on the right subtree are greater than the root node.
Inorder Traversal:It signifies that after traversing the root node, the left subtree is visited first, followed by the right subtree. Inorder traversal refers to the process of traversing the root node between the left and right subtrees. As a result, each node in the inorder traversal gets visited in between its subtrees.
Prerequisite for this problem: To check if a tree is BST or not
Approach 1: Brute force
We must determine whether a node’s left subtree contains any elements bigger than the node’s value, as well as whether the node’s right subtree contains any elements smaller than the node’s value. We’ll create two helper functions, getMin(root) and getMax(root), that return the tree’s minimal and maximum values for a given root. Then we’ll look at each node If the value of the node is greater than or equal to the maximum value in the left subtree Is the node’s value less than or equal to the right subtree’s minimum value? We’ll basically see if this expression is true or not: getMax(root.left)<root.val< getMin(root.right).We are traversing and calling getMax(root.left) and getMin(root.right) for each node.We are traversing and calling getMax(root.left) and getMin(root.right) for each node hence it will cost quadratic time complexity.
Approach 2: Optmized approach
We traversed several portions of the tree many times in the prior approach. Then we go down the tree, keeping track of the min and max allowable values for each node, rather than executing getMin(root) and getMax(root) for each node. This is done by passing the allowable range as a function argument and recursing through the left and right subtrees. We’re only looking at each node once, hence the min and max values should be INT MIN and INT MAX. Here each node is visited only once hence it will cost only linear time complexity.
Approach 3: Using inorder Traversal
We know that traversing a binary search tree in an inorder way will result in sorted order of its elements. We’ll take advantage of this by traversing the tree in reverse order and storing the elements in an array. The array will then be traversed in a linear fashion to see if it is in sorted order. Inorder traversal of BST for storing elements in arr[] + Single loop to check arr[] is sorted or not = O(n) + O(n) = O(n)
Now since we are aware of how to check if a subtree is a binary search tree or not then we can move with our main problem of finding the largest bst in binary tree search. So let’s explore all the different ways to solve this problem.
Approach 1
Start from the root node and do an inorder traversal for the entire tree. For each node X, check whether the subtree rooted with X is a binary search tree or not. If it is a Binary Search Tree, then return the size of the subtree rooted with X. Else, recursively work down the left and right subtrees and return the maximum of values returned by the left and right subtrees. The worst-case time complexity for this approach will reach O(n^2). This is if we consider a skewed tree for worst-case analysis.
Approach 2
The time complexity of this approach is O(n2). In this n is the size of the BST & requires space proportional to the tree’s height for the call stack. We can also improve time complexity to O(n). This is done by traversing the tree in a bottom-up manner where information is exchanged between the child nodes and parent node. This helps determine if the subtree rooted under any node is a BST in constant time.
There is one more optimized approach that can solve this problem in linear time. Just remember, that if a subtree is a BST, then all nodes in its subtree are likewise BSTs. As a result, we’ll recurse down the binary tree, using the information from the left and right subtrees to store the information for the current subtree.
Explanation :
In method 1, we have traversed the tree in a top-down manner. We have also done a Binary Search Tree test for every individual node. But if we traverse the tree in a bottom-up manner, then we can pass information about subtrees to their respective parent. The passed information or data is used by the parent node. This is used to do the Binary Search Tree test (for the parent node) only in constant time or, I would say, O(1) time. A left subtree needs to tell the parent whether it is a Binary Search Tree or not. It also needs to pass the maximum value in it. Hence, one can compare the maximum value with the parent’s data to check the Binary Search Tree property.
Now Similarly, the right subtree also needs to pass the minimum value up to the tree. The subtrees need to pass the following information up to the tree to find the largest BST in all BSTS.
Common FAQs –
Approach 1:
- What is the time complexity of the isBST function?
The time complexity of the isBST function is O(N). This is because we run an inorder traversal inside this function whose time complexity is O(N). - What is the time complexity of the size function?
The time complexity of the size function is O(N). This is because we run an inorder traversal inside this function whose time complexity is O(N). - Why min and max are used in the isBST function?
The min & max specify the range in which the current node’s value should lie to follow the BST property.
Approach 2:
- How did we come to the optimized approach for the problem of finding the Largest BST subtree?
Earlier in approach 1, we traversed from up to down and checked if its subtree is BST or not for each node. But in approach 2, we started from down to up. Then used information returned by the child to the parent to figure out if the current node subtree is BST or not. - How do we determine if the current node subtree is a BST or not?
The current node’s value should be greater than the left child’s subtree maximum value. It should also be smaller than the right child’s minimum value.
Check out this article – 5 Fundamental Steps to Make an App