Find LCA in Binary Tree using RMQ | C ++ Program to find LCA of u and v by reducing the problem to RMQ ; A Binary Tree node ; number of nodes in input tree ; For Euler tour sequence ; Level of nodes in tour sequence ; First occurrences of nodes in tour ; Variable to fill - in euler and level arrays ; log base 2 of x ; A recursive function to get the minimum value in a given range of array indexes . The following are parameters for this function . st -- > Pointer to segment tree index -- > Index of current node in the segment tree . Initially 0 is passed as root is always at index 0 ss & se -- > Starting and ending indexes of the segment represented by current node , i . e . , st [ index ] qs & qe -- > Starting and ending indexes of query range ; If segment of this node is a part of given range , then return the min of the segment ; If segment of this node is outside the given range ; If a part of this segment overlaps with the given range ; Return minimum of elements in range from index qs ( query start ) to qe ( query end ) . It mainly uses RMQUtil ( ) ; Check for erroneous input values ; A recursive function that constructs Segment Tree for array [ ss . . se ] . si is index of current node in segment tree st ; If there is one element in array , store it in current node of segment tree and return ; If there are more than one elements , then recur for left and right subtrees and store the minimum of two values in this node ; Function to construct segment tree from given array . This function allocates memory for segment tree and calls constructSTUtil ( ) to fill the allocated memory ; Allocate memory for segment tree Height of segment tree ; Maximum size of segment tree 2 * pow ( 2 , x ) - 1 ; Fill the allocated memory st ; Return the constructed segment tree ; Recursive version of the Euler tour of T ; if the passed node exists ; insert in euler array ; insert l in level array ; increment index ; if unvisited , mark first occurrence ; tour left subtree if exists , and remark euler and level arrays for parent on return ; tour right subtree if exists , and remark euler and level arrays for parent on return ; Returns LCA of nodes n1 , n2 ( assuming they are present in the tree ) ; Mark all nodes unvisited . Note that the size of firstOccurrence is 1 as node values which vary from 1 to 9 are used as indexes ; To start filling euler and level arrays from index 0 ; Start Euler tour with root node on level 0 ; construct segment tree on level array ; If v before u in Euler tour . For RMQ to work , first parameter ' u ' must be smaller than second ' v ' ; Starting and ending indexes of query range ; query for index of LCA in tour ; return LCA node ; Driver program to test above functions ; Let us create the Binary Tree as shown in the diagram .
#include <bits/stdc++.h> NEW_LINE struct Node { int key ; struct Node * left , * right ; } ; Node * newNode ( int k ) { Node * temp = new Node ; temp -> key = k ; temp -> left = temp -> right = NULL ; return temp ; } #define V  9			 NEW_LINE int euler [ 2 * V - 1 ] ; int level [ 2 * V - 1 ] ; int firstOccurrence [ V + 1 ] ; int ind ; int Log2 ( int x ) { int ans = 0 ; while ( x >>= 1 ) ans ++ ; return ans ; } int RMQUtil ( int index , int ss , int se , int qs , int qe , int * st ) { if ( qs <= ss && qe >= se ) return st [ index ] ; else if ( se < qs ss > qe ) return -1 ; int mid = ( ss + se ) / 2 ; int q1 = RMQUtil ( 2 * index + 1 , ss , mid , qs , qe , st ) ; int q2 = RMQUtil ( 2 * index + 2 , mid + 1 , se , qs , qe , st ) ; if ( q1 == -1 ) return q2 ; else if ( q2 == -1 ) return q1 ; return ( level [ q1 ] < level [ q2 ] ) ? q1 : q2 ; } int RMQ ( int * st , int n , int qs , int qe ) { if ( qs < 0 qe > n -1 qs > qe ) { printf ( " Invalid ▁ Input " ) ; return - 1 ; } return RMQUtil ( 0 , 0 , n - 1 , qs , qe , st ) ; } void constructSTUtil ( int si , int ss , int se , int arr [ ] , int * st ) { if ( ss == se ) st [ si ] = ss ; else { int mid = ( ss + se ) / 2 ; constructSTUtil ( si * 2 + 1 , ss , mid , arr , st ) ; constructSTUtil ( si * 2 + 2 , mid + 1 , se , arr , st ) ; if ( arr [ st [ 2 * si + 1 ] ] < arr [ st [ 2 * si + 2 ] ] ) st [ si ] = st [ 2 * si + 1 ] ; else st [ si ] = st [ 2 * si + 2 ] ; } } int * constructST ( int arr [ ] , int n ) { int x = Log2 ( n ) + 1 ; int max_size = 2 * ( 1 << x ) - 1 ; int * st = new int [ max_size ] ; constructSTUtil ( 0 , 0 , n - 1 , arr , st ) ; return st ; } void eulerTour ( Node * root , int l ) { if ( root ) { euler [ ind ] = root -> key ; level [ ind ] = l ; ind ++ ; if ( firstOccurrence [ root -> key ] == -1 ) firstOccurrence [ root -> key ] = ind - 1 ; if ( root -> left ) { eulerTour ( root -> left , l + 1 ) ; euler [ ind ] = root -> key ; level [ ind ] = l ; ind ++ ; } if ( root -> right ) { eulerTour ( root -> right , l + 1 ) ; euler [ ind ] = root -> key ; level [ ind ] = l ; ind ++ ; } } } int findLCA ( Node * root , int u , int v ) { memset ( firstOccurrence , -1 , sizeof ( int ) * ( V + 1 ) ) ; ind = 0 ; eulerTour ( root , 0 ) ; int * st = constructST ( level , 2 * V - 1 ) ; if ( firstOccurrence [ u ] > firstOccurrence [ v ] ) std :: swap ( u , v ) ; int qs = firstOccurrence [ u ] ; int qe = firstOccurrence [ v ] ; int index = RMQ ( st , 2 * V - 1 , qs , qe ) ; return euler [ index ] ; } int main ( ) { Node * root = newNode ( 1 ) ; root -> left = newNode ( 2 ) ; root -> right = newNode ( 3 ) ; root -> left -> left = newNode ( 4 ) ; root -> left -> right = newNode ( 5 ) ; root -> right -> left = newNode ( 6 ) ; root -> right -> right = newNode ( 7 ) ; root -> left -> right -> left = newNode ( 8 ) ; root -> left -> right -> right = newNode ( 9 ) ; int u = 4 , v = 9 ; printf ( " The ▁ LCA ▁ of ▁ node ▁ % d ▁ and ▁ node ▁ % d ▁ is ▁ node ▁ % d . STRNEWLINE " , u , v , findLCA ( root , u , v ) ) ; return 0 ; }