Given a BST, find the inorder predecessor of a given key in it. If the key does not lie in the BST, return the previous greater node (if any) present in the BST.

An inorder predecessor of a node in the BST is the previous node in the inorder traversal of it. For example, consider the following tree:

Inorder successor and Inorder predecessor


The inorder predecessor of 8 does not exist.
The inorder predecessor of 10 is 8
The inorder predecessor of 12 is 10
The inorder predecessor of 20 is 16

Practice this problem

A node’s inorder predecessor is a node with maximum value in its left subtree, i.e., its left subtree’s right-most child. If the left subtree of the node doesn’t exist, then the inorder predecessor is one of its ancestors. To find which ancestors are the predecessor, move up the tree towards the root until we encounter a node that is the right child of its parent. If any such node is found, then the inorder predecessor is its parent; otherwise, the inorder predecessor does not exist for the node.

Recursive Version

We can recursively check the above conditions. The idea is to search for the given node in the tree and update the predecessor to the current node before visiting its right subtree. If the node is found in the BST, return the maximum value node in its left subtree. If the left subtree of the node doesn’t exist, then the inorder predecessor is one of its ancestors, which is already being updated while searching for the given key.

Following is the C++, Java, and Python implementation of the idea:

C++


Download  Run Code

Java


Download  Run Code

Python


Download  Run Code

Output:
 
The predecessor of node 15 is 12
The predecessor of node 10 is 8
The predecessor of node 20 is 16
The predecessor doesn’t exist for node 8
The predecessor of node 12 is 10
The predecessor of node 16 is 15
The predecessor of node 25 is 20

The time complexity of the above solution is O(n), where n is the size of the BST, and requires space proportional to the tree’s height for the call stack.

Iterative Version

The same algorithm can be easily implemented iteratively as follows in C++, Java, and Python:

C++


Download  Run Code

Java


Download  Run Code

Python


Download  Run Code

Output:
 
The predecessor of node 15 is 12
The predecessor of node 10 is 8
The predecessor of node 20 is 16
The predecessor doesn’t exist for node 8
The predecessor of node 12 is 10
The predecessor of node 16 is 15
The predecessor of node 25 is 20

The time complexity of the above solution is O(n), where n is the size of the BST. The auxiliary space required by the program is O(1).