Given the root of a Binary Search Tree (BST) and an integer key, find its inorder predecessor and inorder successor.
The inorder predecessor is the node with the largest value smaller than key, and the inorder successor is the node with the smallest value greater than key. If either does not exist, return NULL for that position.
[Naive Approach] Maintaining predecessor and successors - O(n) Time and O(1) Space
The idea is to traverse the entire BST while maintaining the inorder predecessor and successor of the given key. For each node, if its value is smaller than the key, it can be a potential predecessor, so we update it if it is greater than the current predecessor. Similarly, if its value is greater than the key, it can be a potential successor, so we update it if it is smaller than the current successor.
C++
#include<iostream>#include<vector>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=nullptr;}};// traversal to find // predecessor and successorvoidpreorder(Node*root,intkey,Node*&pre,Node*&suc){if(root==nullptr)return;if(root->data<key&&(pre==nullptr||pre->data<root->data)){pre=root;}if(root->data>key&&(suc==nullptr||suc->data>root->data)){suc=root;}preorder(root->left,key,pre,suc);preorder(root->right,key,pre,suc);}// return vector with predecessor at // index 0 and successor at index 1vector<Node*>findPreSuc(Node*root,intkey){Node*pre=nullptr;Node*suc=nullptr;preorder(root,key,pre,suc);return{pre,suc};}intmain(){// Create BST:// 50 // / \ // 30 70// / \ / \ // 20 40 60 80intkey=65;Node*root=newNode(50);root->left=newNode(30);root->right=newNode(70);root->left->left=newNode(20);root->left->right=newNode(40);root->right->left=newNode(60);root->right->right=newNode(80);vector<Node*>result=findPreSuc(root,key);Node*pre=result[0];Node*suc=result[1];cout<<(pre?to_string(pre->data):"NULL")<<" ";cout<<(suc?to_string(suc->data):"NULL")<<endl;}
Java
importjava.util.ArrayList;importjava.util.Arrays;// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{// return ArrayList with predecessor at index 0 // and successor at index 1staticArrayList<Node>findPreSuc(Noderoot,intkey){Node[]pre=newNode[1];Node[]suc=newNode[1];preorder(root,key,pre,suc);returnnewArrayList<>(Arrays.asList(pre[0],suc[0]));}// traversal to find predecessor and successorstaticvoidpreorder(Noderoot,intkey,Node[]pre,Node[]suc){if(root==null)return;if(root.data<key&&(pre[0]==null||pre[0].data<root.data)){pre[0]=root;}if(root.data>key&&(suc[0]==null||suc[0].data>root.data)){suc[0]=root;}preorder(root.left,key,pre,suc);preorder(root.right,key,pre,suc);}publicstaticvoidmain(String[]args){// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80intkey=65;Noderoot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);ArrayList<Node>result=findPreSuc(root,key);Nodepre=result.get(0);Nodesuc=result.get(1);System.out.print((pre==null)?"NULL ":(pre.data+" "));System.out.print((suc==null)?"NULL ":(suc.data+" "));}}
Python
# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# traversal to find predecessor and successordefpreorder(root,key,pre,suc):ifrootisNone:returnifroot.data<keyand(pre[0]isNoneorpre[0].data<root.data):pre[0]=rootifroot.data>keyand(suc[0]isNoneorsuc[0].data>root.data):suc[0]=rootpreorder(root.left,key,pre,suc)preorder(root.right,key,pre,suc)# return list with predecessor at index 0 and successor at index 1deffindPreSuc(root,key):pre=[None]suc=[None]preorder(root,key,pre,suc)return[pre[0],suc[0]]if__name__=="__main__":# Create BST:# 50 # / \# 30 70# / \ / \# 20 40 60 80key=65root=Node(50)root.left=Node(30)root.right=Node(70)root.left.left=Node(20)root.left.right=Node(40)root.right.left=Node(60)root.right.right=Node(80)result=findPreSuc(root,key)pre=result[0]suc=result[1]print((str(pre.data)ifpreelse"NULL"),(str(suc.data)ifsucelse"NULL"))
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{// return List with predecessor at index 0 // and successor at index 1staticList<Node>findPreSuc(Noderoot,intkey){Node[]pre=newNode[1];Node[]suc=newNode[1];preorder(root,key,pre,suc);returnnewList<Node>{pre[0],suc[0]};}// traversal to find // predecessor and successorstaticvoidpreorder(Noderoot,intkey,Node[]pre,Node[]suc){if(root==null)return;if(root.data<key&&(pre[0]==null||pre[0].data<root.data)){pre[0]=root;}if(root.data>key&&(suc[0]==null||suc[0].data>root.data)){suc[0]=root;}preorder(root.left,key,pre,suc);preorder(root.right,key,pre,suc);}publicstaticvoidMain(){// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80intkey=65;Noderoot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);List<Node>result=findPreSuc(root,key);Nodepre=result[0];Nodesuc=result[1];Console.Write((pre==null?"NULL ":pre.data+" "));Console.Write((suc==null?"NULL ":suc.data+" "));}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// traversal to find predecessor and successorfunctionpreorder(root,key,pre,suc){if(root===null)return;if(root.data<key&&(pre[0]===null||pre[0].data<root.data)){pre[0]=root;}if(root.data>key&&(suc[0]===null||suc[0].data>root.data)){suc[0]=root;}preorder(root.left,key,pre,suc);preorder(root.right,key,pre,suc);}// return array with predecessor at index 0 and successor at index 1functionfindPreSuc(root,key){letpre=[null];letsuc=[null];preorder(root,key,pre,suc);return[pre[0],suc[0]];}// Driver code// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80letkey=65;letroot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);letresult=findPreSuc(root,key);letpre=result[0];letsuc=result[1];console.log((pre?pre.data:"NULL")+" "+(suc?suc.data:"NULL"));
Output
60 70
[Expected Approach-1] Using Two Traversals - O(h) Time and O(1) Space
The idea is to traverse the BST twice-once to find the predecessor and once to find the successor. For the predecessor, if the current node is smaller than the key, update it as the potential predecessor and move to the right subtree; otherwise, move to the left subtree. Similarly, for the successor, if the current node is greater than the key, update it as the potential successor and move to the left subtree; otherwise, move to the right subtree.
C++
#include<vector>#include<iostream>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intval){data=val;left=right=nullptr;}};// Finding predecessor of keyNode*findPredecessor(Node*root,intkey){Node*predecessor=nullptr;while(root){if(key>root->data){// potential predecessorpredecessor=root;// look for larger predecessorsroot=root->right;}else{root=root->left;}}returnpredecessor;}// Finding successor of keyNode*findSuccessor(Node*root,intkey){Node*successor=nullptr;while(root){if(key<root->data){// potential successorsuccessor=root;// look for smaller successorroot=root->left;}else{root=root->right;}}returnsuccessor;}// return vector with predecessor at index 0 // and successor at index 1vector<Node*>findPreSuc(Node*root,intkey){Node*pre=findPredecessor(root,key);Node*suc=findSuccessor(root,key);return{pre,suc};}intmain(){// Create BST:// 50 // / \ // 30 70// / \ / \ // 20 40 60 80Node*root=newNode(50);root->left=newNode(30);root->right=newNode(70);root->left->left=newNode(20);root->left->right=newNode(40);root->right->left=newNode(60);root->right->right=newNode(80);intkey=65;vector<Node*>result=findPreSuc(root,key);Node*pre=result[0];Node*suc=result[1];cout<<(pre?to_string(pre->data):string("NULL"))<<" "<<(suc?to_string(suc->data):string("NULL"));return0;}
Java
importjava.util.ArrayList;importjava.util.Arrays;// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{// return ArrayList with predecessor at index 0 // and successor at index 1staticArrayList<Node>findPreSuc(Noderoot,intkey){Nodepredecessor=findPredecessor(root,key);Nodesuccessor=findSuccessor(root,key);returnnewArrayList<>(Arrays.asList(predecessor,successor));}// Finding predecessor of keystaticNodefindPredecessor(Noderoot,intkey){Nodepredecessor=null;while(root!=null){if(key>root.data){// potential predecessorpredecessor=root;// look for larger predecessorsroot=root.right;}else{root=root.left;}}returnpredecessor;}// Finding successor of keystaticNodefindSuccessor(Noderoot,intkey){Nodesuccessor=null;while(root!=null){if(key<root.data){// potential successorsuccessor=root;// look for smaller successorsroot=root.left;}else{root=root.right;}}returnsuccessor;}publicstaticvoidmain(String[]args){// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80intkey=65;Noderoot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);ArrayList<Node>result=findPreSuc(root,key);Nodepre=result.get(0);Nodesuc=result.get(1);System.out.print((pre!=null?pre.data:"NULL")+" ");System.out.print(suc!=null?suc.data:"NULL");}}
Python
# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Finding predecessor of keydeffindPredecessor(root,key):predecessor=Nonewhileroot:ifkey>root.data:# potential predecessorpredecessor=root;# look for larger predecessorsroot=root.rightelse:root=root.leftreturnpredecessor# Finding successor of keydeffindSuccessor(root,key):successor=Nonewhileroot:ifkey<root.data:# potential successorsuccessor=root# look for smaller successorroot=root.leftelse:root=root.rightreturnsuccessor# return list with predecessor at index 0 # and successor at index 1deffindPreSuc(root,key):return[findPredecessor(root,key),findSuccessor(root,key)]if__name__=='__main__':# Create BST:# 50 # / \# 30 70# / \ / \# 20 40 60 80root=Node(50)root.left=Node(30)root.right=Node(70)root.left.left=Node(20)root.left.right=Node(40)root.right.left=Node(60)root.right.right=Node(80)key=65pre,suc=findPreSuc(root,key)print((pre.dataifpreelse"NULL"),(suc.dataifsucelse"NULL"))
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{// Finding predecessor of keystaticNodefindPredecessor(Noderoot,intkey){Nodepredecessor=null;while(root!=null){if(key>root.data){// potential predecessorpredecessor=root;// look for larger predecessorsroot=root.right;}else{root=root.left;}}returnpredecessor;}// Finding successor of keystaticNodefindSuccessor(Noderoot,intkey){Nodesuccessor=null;while(root!=null){if(key<root.data){// potential successorsuccessor=root;// look for smaller successorsroot=root.left;}else{root=root.right;}}returnsuccessor;}// return List with predecessor at index 0 // and successor at index 1staticList<Node>findPreSuc(Noderoot,intkey){Nodepre=findPredecessor(root,key);Nodesuc=findSuccessor(root,key);returnnewList<Node>{pre,suc};}staticvoidMain(){// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80Noderoot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);intkey=65;List<Node>result=findPreSuc(root,key);Nodepre=result[0];Nodesuc=result[1];Console.WriteLine($"{(pre != null ? pre.data.ToString() : "NULL")} "+$"{(suc != null ? suc.data.ToString() : "NULL")}");}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=this.right=null;}}// Finding predecessor of keyfunctionfindPredecessor(root,key){letpredecessor=null;while(root){if(key>root.data){// potential predecessorpredecessor=root;// look for larger predecessorsroot=root.right;}else{root=root.left;}}returnpredecessor;}// Finding successor of keyfunctionfindSuccessor(root,key){letsuccessor=null;while(root){if(key<root.data){// potential successorsuccessor=root;// look for smaller successorroot=root.left;}else{root=root.right;}}returnsuccessor;}// return array with predecessor at index 0 // and successor at index 1functionfindPreSuc(root,key){return[findPredecessor(root,key),findSuccessor(root,key)];}// Driver Code// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80letroot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);letkey=65;let[pre,suc]=findPreSuc(root,key);console.log((pre?pre.data:"NULL")+" "+(suc?suc.data:"NULL"));
Output
60 70
[Expected Approach-2] Using Single Traversal - O(h) Time and O(1) Space
The idea is to traverse the BST only once while maintaining both the predecessor and successor. If the current node is smaller than the key, update it as the potential predecessor and move to the right subtree. If it is greater than the key, update it as the potential successor and move to the left subtree. When the key is found, the predecessor is the rightmost node in its left subtree, and the successor is the leftmost node in its right subtree.
Consider the following BST and key = 65:
Initially, pre = NULL, suc = NULL, curr = 50
At 50: 50 < 65, so update pre = 50 and move to the right child.
At 70: 70 > 65, so update suc = 70 and move to the left child.
At 60: 60 < 65, so update pre = 60 and move to the right child.
curr becomes NULL, so the search ends.
Since the key is not present in the BST, the last recorded predecessor and successor are the required answer, i.e., Predecessor = 60 and Successor = 70.
If the key exists, say key = 70, then:
The predecessor is the rightmost node in its left subtree (60).
The successor is the leftmost node in its right subtree (80).
Hence, the answer is: Predecessor = 60 and Successor = 80
C++
#include<vector>#include<iostream>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intval){data=val;left=right=nullptr;}};Node*rightMost(Node*node){while(node->right)node=node->right;returnnode;}Node*leftMost(Node*node){while(node->left)node=node->left;returnnode;}// return vector with predecessor at index 0 // and successor at index 1vector<Node*>findPreSuc(Node*root,intkey){Node*pre=nullptr;Node*suc=nullptr;Node*curr=root;while(curr){if(curr->data<key){pre=curr;// look for predecessor with greater valuecurr=curr->right;}elseif(curr->data>key){suc=curr;// look for successor with smaller valuecurr=curr->left;}else{if(curr->left)pre=rightMost(curr->left);if(curr->right)suc=leftMost(curr->right);break;}}return{pre,suc};}intmain(){intkey=65;// Create BST:// 50 // / \ // 30 70// / \ / \ // 20 40 60 80Node*root=newNode(50);root->left=newNode(30);root->right=newNode(70);root->left->left=newNode(20);root->left->right=newNode(40);root->right->left=newNode(60);root->right->right=newNode(80);vector<Node*>result=findPreSuc(root,key);Node*pre=result[0];Node*suc=result[1];cout<<(pre?to_string(pre->data):"NULL")<<" ";cout<<(suc?to_string(suc->data):"NULL");}
Java
importjava.util.ArrayList;// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{staticNoderightMost(Nodenode){while(node.right!=null){node=node.right;}returnnode;}staticNodeleftMost(Nodenode){while(node.left!=null){node=node.left;}returnnode;}// return ArrayList with predecessor at index 0 // and successor at index 1staticArrayList<Node>findPreSuc(Noderoot,intkey){Nodepre=null,suc=null;Nodecurr=root;while(curr!=null){if(curr.data<key){pre=curr;// look for predecessor with greater valuecurr=curr.right;}elseif(curr.data>key){suc=curr;// look for successor with smaller valuecurr=curr.left;}else{if(curr.left!=null)pre=rightMost(curr.left);if(curr.right!=null)suc=leftMost(curr.right);break;}}ArrayList<Node>result=newArrayList<>();result.add(pre);result.add(suc);returnresult;}publicstaticvoidmain(String[]args){intkey=65;// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80Noderoot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);ArrayList<Node>result=findPreSuc(root,key);Nodepre=result.get(0);Nodesuc=result.get(1);System.out.print((pre==null)?"NULL ":(pre.data+" "));System.out.print((suc==null)?"NULL ":(suc.data+" "));}}
Python
# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=NonedefrightMost(node):whilenode.right:node=node.rightreturnnodedefleftMost(node):whilenode.left:node=node.leftreturnnode# return list with predecessor at index 0 # and successor at index 1deffindPreSuc(root,key):pre,suc=None,Nonecurr=rootwhilecurr:ifcurr.data<key:pre=curr# look for predecessor with greater valuecurr=curr.rightelifcurr.data>key:suc=curr# look for successor with smaller valuecurr=curr.leftelse:ifcurr.left:pre=rightMost(curr.left)ifcurr.right:suc=leftMost(curr.right)breakreturn[pre,suc]if__name__=="__main__":key=65# Create BST:# 50 # / \# 30 70# / \ / \# 20 40 60 80root=Node(50)root.left=Node(30)root.right=Node(70)root.left.left=Node(20)root.left.right=Node(40)root.right.left=Node(60)root.right.right=Node(80)pre,suc=findPreSuc(root,key)print((pre.dataifpreelse"NULL"),(suc.dataifsucelse"NULL"))
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGfG{staticNodeRightMost(Nodenode){while(node.right!=null)node=node.right;returnnode;}staticNodeLeftMost(Nodenode){while(node.left!=null)node=node.left;returnnode;}// return List with predecessor at index 0 // and successor at index 1publicstaticList<Node>FindPreSuc(Noderoot,intkey){Nodepre=null,suc=null;Nodecurr=root;while(curr!=null){if(curr.data<key){pre=curr;// look for predecessor with greater valuecurr=curr.right;}elseif(curr.data>key){suc=curr;// look for successor with smaller valuecurr=curr.left;}else{if(curr.left!=null)pre=RightMost(curr.left);if(curr.right!=null)suc=LeftMost(curr.right);break;}}returnnewList<Node>{pre,suc};}publicstaticvoidMain(){intkey=65;// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80Noderoot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);List<Node>result=FindPreSuc(root,key);Nodepre=result[0];Nodesuc=result[1];Console.Write((pre==null?"NULL ":pre.data+" "));Console.Write((suc==null?"NULL":suc.data.ToString()));}}
Javascript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}functionleftMost(node){while(node.left)node=node.left;returnnode;}functionrightMost(node){while(node.right)node=node.right;returnnode;}// return array with predecessor at index 0 // and successor at index 1functionfindPreSuc(root,key){letpre=null,suc=null;letcurr=root;while(curr){if(curr.data<key){pre=curr;// look for predecessor with greater valuecurr=curr.right;}elseif(curr.data>key){suc=curr;// look for successor with smaller valuecurr=curr.left;}else{if(curr.left)pre=rightMost(curr.left);if(curr.right)suc=leftMost(curr.right);break;}}return[pre,suc];}// Driver code// Create BST:// 50 // / \// 30 70// / \ / \// 20 40 60 80letkey=65;letroot=newNode(50);root.left=newNode(30);root.right=newNode(70);root.left.left=newNode(20);root.left.right=newNode(40);root.right.left=newNode(60);root.right.right=newNode(80);let[pre,suc]=findPreSuc(root,key);console.log((pre?pre.data:"NULL")+" "+(suc?suc.data:"NULL"));