Given an array of n elements and two integers a, b which belong to the given array. Create a Binary Search Tree by inserting elements from arr[0] to arr[n-1]. The task is to find the maximum element in the path from a to b.
[Naive approach] Using hashing - O(n * log n) Time and O(n) Space
The idea is to use a hashmap to store the parent node of each node in the binary search tree. We can start from both the given nodes and traverse up the tree, storing the nodes encountered in a set. Once we reach the root or a common ancestor of the two nodes, we can traverse down the tree from each node and find the maximum element encountered in the set of nodes.
Algorithm steps for the above approach:
Create an empty hash table to store the parent node of each node in the binary search tree.
Perform a depth-first search (DFS) traversal of the binary search tree and populate the hash table with the parent node of each node.
Initialize two pointers, say p1 and p2, to the given nodes.
Initialize two empty sets, say s1 and s2, to store the nodes encountered while traversing up the tree from p1 and p2, respectively.
While p1 and p2 are not equal, do the following:
If p1 is not null, add it to set s1 and update p1 to its parent node using the hash table.
If p2 is not null, add it to set s2 and update p2 to its parent node using the hash table.
Find the intersection set of s1 and s2, i.e., the set of nodes that are common to both s1 and s2.
In this intersection find maximum element and return it.
Below is the implementation of the above approach:
C++
// C++ program to find maximum element in the path// between two Nodes of Binary Search Tree.#include<bits/stdc++.h>usingnamespacestd;classNode{public:intdata;Node*left,*right;Node(intx){data=x;left=right=nullptr;}};// Insert a new Node in Binary Search TreevoidinsertNode(Node*&root,intx){Node*current=root,*parent=nullptr;// Traverse to the correct position for insertionwhile(current!=nullptr){parent=current;if(x<current->data)current=current->left;elsecurrent=current->right;}// Insert new Node at the correct positionif(parent==nullptr)root=newNode(x);elseif(x<parent->data)parent->left=newNode(x);elseparent->right=newNode(x);}// DFS to populate parent map for each nodevoiddfs(Node*root,unordered_map<Node*,Node*>&parentMap,Node*parent=nullptr){if(!root)return;// Store the parent of the current nodeif(parent!=nullptr){parentMap[root]=parent;}// Recur for left and right childrendfs(root->left,parentMap,root);dfs(root->right,parentMap,root);}// Function to find the node with the given value in the BSTNode*findNode(Node*root,intval){if(!root)returnnullptr;if(root->data==val)returnroot;Node*leftResult=findNode(root->left,val);if(leftResult)returnleftResult;returnfindNode(root->right,val);}// Find maximum element in the path between two nodes in BSTintfindMaxElement(Node*root,intx,inty){unordered_map<Node*,Node*>parentMap;// Populate parent map with DFSdfs(root,parentMap);// Find the nodes corresponding to the // values x and yNode*p1=findNode(root,x);Node*p2=findNode(root,y);// If nodes not foundif(!p1||!p2)return-1;// Sets to store nodes encountered // while traversing up the treeunordered_set<Node*>s1,s2;// Variable to store the maximum // element in the pathintmaxElement=INT_MIN;// Traverse up the tree from p1 and p2 // and add nodes to sets s1 and s2while(p1!=p2){if(p1){s1.insert(p1);maxElement=max(maxElement,p1->data);// Move to parent nodep1=parentMap[p1];}if(p2){s2.insert(p2);maxElement=max(maxElement,p2->data);p2=parentMap[p2];}// Check if there's a common node// in both setsif(s1.count(p2))break;if(s2.count(p1))break;}// Now both p1 and p2 point to their Lowest// Common Ancestor (LCA)maxElement=max(maxElement,p1->data);returnmaxElement;}intmain(){vector<int>arr={18,36,9,6,12,10,1,8};inta=1,b=10;intn=arr.size();Node*root=newNode(arr[0]);for(inti=1;i<n;i++)insertNode(root,arr[i]);cout<<findMaxElement(root,a,b)<<endl;return0;}
Java
// Java program to find the maximum element in the path// between two Nodes of Binary Search Tree.importjava.util.*;classNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGfG{// Insert a new Node in Binary Search TreestaticvoidinsertNode(Noderoot,intx){Nodecurrent=root,parent=null;// Traverse to the correct position // for insertionwhile(current!=null){parent=current;if(x<current.data)current=current.left;elsecurrent=current.right;}// Insert new Node at the correct positionif(parent==null)root=newNode(x);elseif(x<parent.data)parent.left=newNode(x);elseparent.right=newNode(x);}// DFS to populate parent map for each nodestaticvoiddfs(Noderoot,Map<Node,Node>parentMap,Nodeparent){if(root==null)return;// Store the parent of the current nodeif(parent!=null){parentMap.put(root,parent);}// Recur for left and right childrendfs(root.left,parentMap,root);dfs(root.right,parentMap,root);}// Function to find the node with the given// value in the BSTstaticNodefindNode(Noderoot,intval){if(root==null)returnnull;if(root.data==val)returnroot;NodeleftResult=findNode(root.left,val);if(leftResult!=null)returnleftResult;returnfindNode(root.right,val);}// Find maximum element in the path between// two nodes in BSTstaticintfindMaxElement(Noderoot,intx,inty){Map<Node,Node>parentMap=newHashMap<>();// Populate parent map with DFSdfs(root,parentMap,null);// Find the nodes corresponding to // the values x and yNodep1=findNode(root,x);Nodep2=findNode(root,y);// If nodes not foundif(p1==null||p2==null)return-1;// Sets to store nodes encountered // while traversing up the treeSet<Node>s1=newHashSet<>();Set<Node>s2=newHashSet<>();// Variable to store the maximum element // in the pathintmaxElement=Integer.MIN_VALUE;// Traverse up the tree from p1 and p2 // and add nodes to sets s1 and s2while(p1!=p2){if(p1!=null){s1.add(p1);maxElement=Math.max(maxElement,p1.data);// Move to parent nodep1=parentMap.get(p1);}if(p2!=null){s2.add(p2);maxElement=Math.max(maxElement,p2.data);p2=parentMap.get(p2);}// Check if there's a common node in both setsif(s1.contains(p2))break;if(s2.contains(p1))break;}// Now both p1 and p2 point to their // Lowest Common Ancestor (LCA)maxElement=Math.max(maxElement,p1.data);returnmaxElement;}publicstaticvoidmain(String[]args){int[]arr={18,36,9,6,12,10,1,8};inta=1,b=10;intn=arr.length;Noderoot=newNode(arr[0]);for(inti=1;i<n;i++)insertNode(root,arr[i]);System.out.println(findMaxElement(root,a,b));}}
Python
# Python program to find maximum element in the path# between two Nodes of Binary Search Tree.classNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Insert a new Node in Binary Search Treedefinsert_node(root,x):current=rootparent=None# Traverse to the correct position for insertionwhilecurrentisnotNone:parent=currentifx<current.data:current=current.leftelse:current=current.right# Insert new Node at the correct positionifparentisNone:root=Node(x)elifx<parent.data:parent.left=Node(x)else:parent.right=Node(x)# DFS to populate parent map for each nodedefdfs(root,parent_map,parent=None):ifrootisNone:return# Store the parent of the current nodeifparentisnotNone:parent_map[root]=parent# Recur for left and right childrendfs(root.left,parent_map,root)dfs(root.right,parent_map,root)# Function to find the node with the given# value in the BSTdeffind_node(root,val):ifrootisNone:returnNoneifroot.data==val:returnrootleft_result=find_node(root.left,val)ifleft_result:returnleft_resultreturnfind_node(root.right,val)# Find maximum element in the path between # two nodes in BSTdeffind_max_element(root,x,y):parent_map={}# Populate parent map with DFSdfs(root,parent_map)# Find the nodes corresponding to the # values x and yp1=find_node(root,x)p2=find_node(root,y)# If nodes not foundifnotp1ornotp2:return-1# Sets to store nodes encountered # while traversing up the trees1=set()s2=set()# Variable to store the maximum element in the pathmax_element=float('-inf')# Traverse up the tree from p1 and p2 # and add nodes to sets s1 and s2whilep1!=p2:ifp1:s1.add(p1)max_element=max(max_element,p1.data)# Move to parent nodep1=parent_map.get(p1)ifp2:s2.add(p2)max_element=max(max_element,p2.data)p2=parent_map.get(p2)# Check if there's a common node in both setsifp2ins1:breakifp1ins2:break# Now both p1 and p2 point to their# Lowest Common Ancestor (LCA)max_element=max(max_element,p1.data)returnmax_elementif__name__=="__main__":arr=[18,36,9,6,12,10,1,8]a,b=1,10n=len(arr)root=Node(arr[0])foriinrange(1,n):insert_node(root,arr[i])print(find_max_element(root,a,b))
C#
// C# program to find the maximum element in the path// between two Nodes of Binary Search Tree.usingSystem;usingSystem.Collections.Generic;classNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGfG{// Insert a new Node in Binary Search TreestaticpublicvoidinsertNode(Noderoot,intx){Nodecurrent=root,parent=null;// Traverse to the correct position// for insertionwhile(current!=null){parent=current;if(x<current.data)current=current.left;elsecurrent=current.right;}// Insert new Node at the correct// positionif(parent==null)root=newNode(x);elseif(x<parent.data)parent.left=newNode(x);elseparent.right=newNode(x);}// DFS to populate parent map for each nodestaticpublicvoiddfs(Noderoot,Dictionary<Node,Node>parentMap,Nodeparent){if(root==null)return;// Store the parent of the current nodeif(parent!=null){parentMap[root]=parent;}// Recur for left and right childrendfs(root.left,parentMap,root);dfs(root.right,parentMap,root);}// Function to find the node with the given// value in the BSTstaticpublicNodefindNode(Noderoot,intval){if(root==null)returnnull;if(root.data==val)returnroot;NodeleftResult=findNode(root.left,val);if(leftResult!=null)returnleftResult;returnfindNode(root.right,val);}// Find maximum element in the path between // two nodes in BSTstaticpublicintfindMaxElement(Noderoot,intx,inty){Dictionary<Node,Node>parentMap=newDictionary<Node,Node>();// Populate parent map with DFSdfs(root,parentMap,null);// Find the nodes corresponding to // the values x and yNodep1=findNode(root,x);Nodep2=findNode(root,y);// If nodes not foundif(p1==null||p2==null)return-1;// Sets to store nodes encountered // while traversing up the treeHashSet<Node>s1=newHashSet<Node>();HashSet<Node>s2=newHashSet<Node>();// Variable to store the maximum element // in the pathintmaxElement=int.MinValue;// Traverse up the tree from p1 and p2 // and add nodes to sets s1 and s2while(p1!=p2){if(p1!=null){s1.Add(p1);maxElement=Math.Max(maxElement,p1.data);// Move to parent nodep1=parentMap[p1];}if(p2!=null){s2.Add(p2);maxElement=Math.Max(maxElement,p2.data);p2=parentMap[p2];}// Check if there's a common node in both setsif(s1.Contains(p2))break;if(s2.Contains(p1))break;}// Now both p1 and p2 point to their Lowest // Common Ancestor (LCA)maxElement=Math.Max(maxElement,p1.data);returnmaxElement;}staticvoidMain(){int[]arr={18,36,9,6,12,10,1,8};inta=1,b=10;intn=arr.Length;Noderoot=newNode(arr[0]);for(inti=1;i<n;i++)insertNode(root,arr[i]);Console.WriteLine(findMaxElement(root,a,b));}}
JavaScript
// JavaScript program to find the maximum element in the path// between two Nodes of Binary Search Tree.classNode{constructor(x){this.data=x;this.left=this.right=null;}}// Insert a new Node in Binary Search TreefunctioninsertNode(root,x){letcurrent=root,parent=null;// Traverse to the correct position for insertionwhile(current!==null){parent=current;if(x<current.data)current=current.left;elsecurrent=current.right;}// Insert new Node at the correct positionif(parent===null)root=newNode(x);elseif(x<parent.data)parent.left=newNode(x);elseparent.right=newNode(x);}// DFS to populate parent map for each nodefunctiondfs(root,parentMap,parent=null){if(root===null)return;// Store the parent of the current nodeif(parent!==null){parentMap.set(root,parent);}// Recur for left and right childrendfs(root.left,parentMap,root);dfs(root.right,parentMap,root);}// Function to find the node with the given // value in the BSTfunctionfindNode(root,val){if(root===null)returnnull;if(root.data===val)returnroot;letleftResult=findNode(root.left,val);if(leftResult!==null)returnleftResult;returnfindNode(root.right,val);}// Find maximum element in the path// between two nodes in BSTfunctionfindMaxElement(root,x,y){letparentMap=newMap();// Populate parent map with DFSdfs(root,parentMap);// Find the nodes corresponding to the// values x and yletp1=findNode(root,x);letp2=findNode(root,y);// If nodes not foundif(p1===null||p2===null)return-1;// Sets to store nodes encounteredlets1=newSet();lets2=newSet();// Variable to store the maximum // element in the pathletmaxElement=-Infinity;// Traverse up the tree from p1 and p2 // and add nodes to sets s1 and s2while(p1!==p2){if(p1!==null){s1.add(p1);maxElement=Math.max(maxElement,p1.data);// Move to parent nodep1=parentMap.get(p1);}if(p2!==null){s2.add(p2);maxElement=Math.max(maxElement,p2.data);p2=parentMap.get(p2);}// Check if there's a common node in both setsif(s1.has(p2))break;if(s2.has(p1))break;}// Now both p1 and p2 point to their Lowest // Common Ancestor (LCA)maxElement=Math.max(maxElement,p1.data);returnmaxElement;}letarr=[18,36,9,6,12,10,1,8];leta=1,b=10;letn=arr.length;letroot=newNode(arr[0]);for(leti=1;i<n;i++)insertNode(root,arr[i]);console.log(findMaxElement(root,a,b));
Output
12
[Expected approach] Using LCA of two node - O(h) Time and O(h) Space
The idea is to find Lowest Common Ancestor of node 'a' and node 'b'. Then search maximum node between LCA and 'a', and also find the maximum node between LCA and 'b'. The answer will be maximum node of two.
Below is the implementation of the above algorithm:
C++
// C++ program to find maximum element in the path// between two Nodes of Binary Search Tree.#include<bits/stdc++.h>usingnamespacestd;classNode{public:Node*left,*right;intdata;Node(intx){data=x;left=right=nullptr;}};// Insert a new Node in Binary Search Tree.voidinsertNode(structNode*root,intx){Node*current=root,*parent=nullptr;while(current!=nullptr){parent=current;if(current->data<x)current=current->right;elsecurrent=current->left;}if(parent==nullptr)current=newNode(x);else{if(parent->data<x)parent->right=newNode(x);elseparent->left=newNode(x);}}// Return the maximum element between a Node// and its given ancestor.intmaxelpath(Node*root,intx){Node*current=root;intmx=INT_MIN;// Traversing the path between ancestor and// Node and finding maximum element.while(current->data!=x){if(current->data>x){mx=max(mx,current->data);current=current->left;}else{mx=max(mx,current->data);current=current->right;}}returnmax(mx,x);}// Return maximum element in the path between// two given Node of BST.intmaximumElement(Node*root,intx,inty){Node*current=root;// Finding the LCA of Node x and Node ywhile((x<current->data&&y<current->data)||(x>current->data&&y>current->data)){// Checking if both the Node lie on the// left side of the parent p.if(x<current->data&&y<current->data)current=current->left;// Checking if both the Node lie on the// right side of the parent p.elseif(x>current->data&&y>current->data)current=current->right;}// Return the maximum of maximum elements occur// in path from ancestor to both Node.returnmax(maxelpath(current,x),maxelpath(current,y));}intmain(){intarr[]={18,36,9,6,12,10,1,8};inta=1,b=10;intn=sizeof(arr)/sizeof(arr[0]);Node*root=newNode(arr[0]);for(inti=1;i<n;i++)insertNode(root,arr[i]);cout<<maximumElement(root,a,b)<<endl;return0;}
Java
// Java program to find maximum element in the path// between two Nodes of Binary Search Tree.importjava.util.*;classNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGfG{// Insert a new Node in Binary Search TreestaticvoidinsertNode(Noderoot,intx){Nodecurrent=root,parent=null;// Traverse to the correct // position for insertionwhile(current!=null){parent=current;if(x<current.data)current=current.left;elsecurrent=current.right;}// Insert new Node at the correct // positionif(parent==null)root=newNode(x);elseif(x<parent.data)parent.left=newNode(x);elseparent.right=newNode(x);}// Find maximum element in the path from // an ancestor to a nodestaticintmaxInPath(Noderoot,intx){intmaxElement=Integer.MIN_VALUE;Nodecurrent=root;// Traverse the path from root to the // target node 'x'while(current!=null&¤t.data!=x){maxElement=Math.max(maxElement,current.data);if(x<current.data)current=current.left;elsecurrent=current.right;}returnMath.max(maxElement,x);}// Find maximum element in the path between two// nodes in BSTstaticintfindMaxElement(Noderoot,intx,inty){Nodecurrent=root;// Find Lowest Common Ancestor (LCA) of x and ywhile((x<current.data&&y<current.data)||(x>current.data&&y>current.data)){if(x<current.data&&y<current.data)current=current.left;elseif(x>current.data&&y>current.data)current=current.right;}// Find maximum elements in paths from LCA // to x and LCA to yreturnMath.max(maxInPath(current,x),maxInPath(current,y));}publicstaticvoidmain(String[]args){int[]arr={18,36,9,6,12,10,1,8};inta=1,b=10;Noderoot=newNode(arr[0]);for(inti=1;i<arr.length;i++)insertNode(root,arr[i]);System.out.println(findMaxElement(root,a,b));}}
Python
# Python program to find maximum element in the path# between two Nodes of Binary Search Tree.classNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Insert a new Node in Binary Search TreedefinsertNode(root,x):current=rootparent=None# Traverse to the correct position for insertionwhilecurrentisnotNone:parent=currentifx<current.data:current=current.leftelse:current=current.right# Insert new Node at the correct positionifparentisNone:root=Node(x)elifx<parent.data:parent.left=Node(x)else:parent.right=Node(x)# Find maximum element in the path from an# ancestor to a nodedefmaxInPath(root,x):maxElement=float('-inf')current=root# Traverse the path from root to the# target node 'x'whilecurrentisnotNoneandcurrent.data!=x:maxElement=max(maxElement,current.data)ifx<current.data:current=current.leftelse:current=current.rightreturnmax(maxElement,x)# Find maximum element in the path between# two nodes in BSTdeffindMaxElement(root,x,y):current=root# Find Lowest Common Ancestor (LCA) of x and ywhile(x<current.dataandy<current.data) \
or(x>current.dataandy>current.data):ifx<current.dataandy<current.data:current=current.leftelifx>current.dataandy>current.data:current=current.right# Find maximum elements in paths from LCA to# x and LCA to yreturnmax(maxInPath(current,x),maxInPath(current,y))if__name__=="__main__":arr=[18,36,9,6,12,10,1,8]a,b=1,10root=Node(arr[0])foriinrange(1,len(arr)):insertNode(root,arr[i])print(findMaxElement(root,a,b))
C#
// C# program to find maximum element in the path// between two Nodes of Binary Search Tree.usingSystem;classNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGfG{// Insert a new Node in Binary Search TreestaticvoidinsertNode(Noderoot,intx){Nodecurrent=root,parent=null;// Traverse to the correct position// for insertionwhile(current!=null){parent=current;if(x<current.data)current=current.left;elsecurrent=current.right;}// Insert new Node at the correct positionif(parent==null)root=newNode(x);elseif(x<parent.data)parent.left=newNode(x);elseparent.right=newNode(x);}// Find maximum element in the path from an // ancestor to a nodestaticintmaxInPath(Noderoot,intx){intmaxElement=int.MinValue;Nodecurrent=root;// Traverse the path from root to the target node 'x'while(current!=null&¤t.data!=x){maxElement=Math.Max(maxElement,current.data);if(x<current.data)current=current.left;elsecurrent=current.right;}returnMath.Max(maxElement,x);}// Find maximum element in the path between two nodes in BSTstaticintfindMaxElement(Noderoot,intx,inty){Nodecurrent=root;// Find Lowest Common Ancestor (LCA) of x and ywhile((x<current.data&&y<current.data)||(x>current.data&&y>current.data)){if(x<current.data&&y<current.data)current=current.left;elseif(x>current.data&&y>current.data)current=current.right;}// Find maximum elements in paths from// LCA to x and LCA to yreturnMath.Max(maxInPath(current,x),maxInPath(current,y));}staticvoidMain(){int[]arr={18,36,9,6,12,10,1,8};inta=1,b=10;Noderoot=newNode(arr[0]);for(inti=1;i<arr.Length;i++)insertNode(root,arr[i]);Console.WriteLine(findMaxElement(root,a,b));}}
JavaScript
// JavaScript program to find maximum element in the path// between two Nodes of Binary Search Tree.classNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// Insert a new Node in Binary Search TreefunctioninsertNode(root,x){letcurrent=root,parent=null;// Traverse to the correct position for insertionwhile(current!==null){parent=current;if(x<current.data)current=current.left;elsecurrent=current.right;}// Insert new Node at the correct positionif(parent===null)root=newNode(x);elseif(x<parent.data)parent.left=newNode(x);elseparent.right=newNode(x);}// Find maximum element in the path from an // ancestor to a nodefunctionmaxInPath(root,x){letmaxElement=-Infinity;letcurrent=root;// Traverse the path from root to the target node 'x'while(current!==null&¤t.data!==x){maxElement=Math.max(maxElement,current.data);if(x<current.data)current=current.left;elsecurrent=current.right;}returnMath.max(maxElement,x);}// Find maximum element in the path between// two nodes in BSTfunctionfindMaxElement(root,x,y){letcurrent=root;// Find Lowest Common Ancestor (LCA) of x and ywhile((x<current.data&&y<current.data)||(x>current.data&&y>current.data)){if(x<current.data&&y<current.data)current=current.left;elseif(x>current.data&&y>current.data)current=current.right;}// Find maximum elements in paths from LCA to // x and LCA to yreturnMath.max(maxInPath(current,x),maxInPath(current,y));}constarr=[18,36,9,6,12,10,1,8];consta=1,b=10;constroot=newNode(arr[0]);for(leti=1;i<arr.length;i++){insertNode(root,arr[i]);}console.log(findMaxElement(root,a,b));