BST - 1
BST - 1
Introduction
● These are the specific types of binary trees.
● These are inspired by the binary search algorithm.
● Time complexity on insertion, deletion, and searching reduces significantly as
it works on the principle of binary search rather than linear search, as in the
case of normal binary trees (will discuss it further).
1
Example: The left tree is a binary search tree and the right tree is not a binary
search tree (This because the BST property is not satisfied at node 6. Its child with key 2,
is less than its parent with key 3, which is a violation, as all the nodes on the right
subtree of root node 3, must have keys greater than or equal to 3).
Example: Insert {45, 68, 35, 42, 15, 64, 78} in a BST in the order they are given.
1. Since the tree is empty, so the first node will automatically be the root node.
2. Now, we have to insert 68, which is greater than 45, so it will go on the right
side of the root node.
2
3. To insert 35, we will start from the root node. Since 35 is smaller than 45, it
will be inserted on the left side.
4. Moving on to inserting 42. We can see that 42 < 45, so it will be placed on the
left side of the root node. Now, we will check the same on the left subtree.
We can see that 42 > 35 means 42 will be the right child of 35, which is still a
part of the left subtree of the root node.
3
5. Now, to insert 15, we will follow the same approach starting from the root
node. Here, 15 < 45, which means 15 will be a part of the left subtree. As 15 <
35, we will continue to move towards the left. As the left subtree of 35 is
empty, so 15 will be the left child of 35.
6. Continuing further, to insert 64, we know that 64 > root node’s data, but less
than 68, hence 64 will be the left child of 68.
4
7. Finally, we have to insert 78. We can see that 78 > 45 and 78 > 68, so 78 will
be the right child of 68.
Note:
● If we follow the inorder traversal of the final BST, we will get the sorted
array.
● As seen above, to insert an element in the BST, we will be traversing till either
the left subtree’s leaf node or right subtree’s leaf node, in the worst-case
scenario.
5
● Hence, the time complexity of insertion for each node is O(log(H)) (where
H is the height of the tree).
● For inserting N nodes, complexity will be O(N*log(H)).
Approach: As the given tree is BST, we can use the binary search algorithm. Using
recursion will make it easier.
Base Case:
● If the tree is empty, it means that the root node is NULL, then we will simply
return NULL as the node is not present.
● Suppose if root’s data is equal to x, we don’t need to traverse forward in this
tree as the target value has been found out, so we will simply return the root
from here.
Small Calculation:
● In the case of BST, we’ll only check for the condition of binary search, i.e., if x
is greater than the root’s data, then we will make a recursive call over the
right subtree; otherwise, the recursive call will be made on the left subtree.
● This way, we are entirely discarding half the tree to be searched as done in
case of a binary search. Therefore, the time complexity of searching is
O(log(H)) (where H is the height of BST).
Recursive call: After figuring out which way to move, we can make recursive calls
on either left or right subtree. This way, we will be able to search the given element
in a BST.
Note: The code written from the above insights can be accessed in the solution tab
in the question itself.
6
Problem Statement: Print elements in a range
Given a BST and a range (L, R), we need to figure out all the elements of BST
that are present in the given range inclusive of L and R.
Approach: We will be using recursion and binary searching for the same.
Base case: If the root is NULL, it means we don’t have any tree to check upon, and
we can simply return.
Recursive call: Recursive call will be made as per the small calculation part onto
the left and right subtrees. In this way, we will be able to figure out all the elements
in the range.
Note: Try to code this yourself, and refer to the solution tab in case of any doubts.
Approach: We will simply traverse the binary tree and check if the nodes satisfy the
BST Property. Thus we will check the following cases:
● If the node’s value is greater than the value of the node on it’s left.
● If the node’s value is smaller than the value of the node on its right.
7
Important Case: Don’t just compare the direct left and right children of the node;
instead, we need to compare every node in the left and right subtree with the
node’s value. Consider the following case:
● Here, it can be seen that for root, the left subtree is a BST, and the right
subtree is also a BST (individually).
● But the complete tree is not a BST. This is because a node with value 5 lies on
the right side of the root node with value 20, whereas it should be on the left
side of the root node.
● Hence, even though the individual subtrees are BSTs, it is also possible that
the complete binary tree is not a BST. Hence, this third condition must also
be checked.
To check over this condition, we will keep track of the minimum and maximum
values of the right and left subtrees correspondingly, and at last, we will simply
compare them with root.
● The left subtree’s maximum value should be less than the root’s data.
● The right subtree’s minimum value should be greater than the root’s data.
Now, let’s look at the Python code for this approach using this approach.
8
def minTree(root):#Returns minimum value in a subtree
if (root == None):#If root is None, it implies empty tree
return 100000 #Return a large number in this case
leftMin = minTree(root.left) #Find min in left subtree
rightMin = minTree(root.right) #Find min in right subtree
return min(leftMin, rightMin, root.data) #Return overall min
def isBST(root)
if (root== None):#If root is None, it implies empty tree
return True #Empty tree is a BST
Time Complexity: In the isBST() function, we are traversing each node, and for
each node, we are then calculating the minimum and maximum value by again
traversing that complete subtree’s height. Hence, if there are N nodes in total and
the height of the tree is H, then the time complexity will be O(N*H).
9
● We now wish to calculate these values, while checking the isBST condition
itself, to get rid of another cycle of iterations.
● We will follow a similar approach as that of the diameter calculation of binary
trees.
● At each stage, we will return the maximum value, minimum value, and the
BST status (True/False) for each node of the tree, in the form of a tuple.
Let’s look at its implementation now:
def isBST2(root):
if root == None:
return 100000, -100000, True
Time Complexity: Here, we are going to each node and doing a constant amount
of work. Hence, the time complexity for N nodes will be of O(N).
10
Approach: We will be checking on the left subtree, right subtree, and combined
tree without returning a tuple of maximum and minimum values. We will be using
the concept of default arguments over here. Check the code below:
Time Complexity: Here also, we are just traversing each node and doing constant
work on each of them; hence time complexity remains the same, i.e. O(n).
Approach:
● Suppose we take the first element as the root node, then the tree will be
skewed as the array is sorted.
● To get a balanced tree (so that searching and other operations can be
performed in O(log(n)) time), we will be using the binary search technique.
11
● Figure out the middle element and mark it as the root.
● This is done so that the tree can be divided into almost 2 equal parts, as half
the elements which will be greater than the root, will form the right subtree
(These elements are present to its right).
● The elements in the other half, which are less than the root, will form the left
subtree (These elements are present to its left).
● Just put root’s left child to be the recursive call made on the left portion of
the array and root’s right child to be the recursive call made on the right
portion of the array.
● Try it yourself and refer to the solution tab for code.
12