Given a binary tree, the task is to find the distance between two keys in a binary tree, no parent pointers are given. The distance between two nodes is the minimum number of edges to be traversed to reach one node from other.
We have already discussed a method which uses segment tree to reduce the query time to O(logn), here the task is to reduce query time to O(1) by compromising space complexity to O(n logn). In this post, we will use Sparse table instead of segment tree for finding the minimum in given range, which uses dynamic programming and bit manipulation to achieve O(1) query time.
A sparse table will preprocess the minimum values of given range for L array in Nlogn space i.e. each node will contain chain of values of log(i) length where i is the index of the ith node in L array. Each entry in the sparse table says M[i][j] will represent the index of the minimum value in the subarray starting at i having length 2^j.
The distance between two nodes can be obtained in terms of lowest common ancestor.Â
Dist(n1, n2) = Level[n1] + Level[n2] - 2*Level[lca]
This problem can be breakdown into:Â
- Finding levels of each node
- Finding the Euler tour of binary tree
- Building sparse table for LCA.
These steps are explained below :Â Â
- Find the levels of each node by applying level order traversal.
- Find the LCA of two nodes in binary tree in O(logn) by Storing Euler tour of Binary tree in array and computing two other arrays with the help of levels of each node and Euler tour.Â
These steps are shown below:
- First, find Euler Tour of binary tree.Â
Â
- Then, store levels of each node in Euler array.Â
- Then, store First occurrences of all nodes of binary tree in Euler array. H stores the indices of nodes from Euler array, so that range of query for finding minimum can be minimized and their by further optimizing the query time.Â
Â
- Then build sparse table on L array and find the minimum value say X in range (H[A] to H[B]). Then, we use the index of value X as an index to Euler array to get LCA, i.e. Euler[index(X)].Â
Let, A=8 and B=5.Â- H[8]= 1 and H[5]=2Â
- we get min value in L array between 1 and 2 as X=0, index=7Â
- Then, LCA= Euler[7], i.e LCA=1.
- Finally, apply distance formula discussed above to get the distance between two nodes.
Implementation:
C++
#include <bits/stdc++.h> #define MAX 100001 using namespace std; Â
/* A tree node structure */ struct Node { Â Â Â Â int data; Â Â Â Â struct Node* left; Â Â Â Â struct Node* right; }; Â
/* Utility function to create a new Binary Tree node */ struct Node* newNode( int data) { Â Â Â Â struct Node* temp = new struct Node; Â Â Â Â temp->data = data; Â Â Â Â temp->left = temp->right = NULL; Â Â Â Â return temp; } Â
// Array to store level of each node int level[MAX]; Â
// Utility Function to store level of all nodes void FindLevels( struct Node* root) { Â Â Â Â if (!root) Â Â Â Â Â Â Â Â return ; Â
    // queue to hold tree node with level     queue<pair< struct Node*, int > > q; Â
    // let root node be at level 0     q.push({ root, 0 });     pair< struct Node*, int > p; Â
    // Do level Order Traversal of tree     while (!q.empty()) {         p = q.front();         q.pop(); Â
        // Node p.first is on level p.second         level[p.first->data] = p.second; Â
        // If left child exits, put it in queue         // with current_level +1         if (p.first->left)             q.push({ p.first->left, p.second + 1 }); Â
        // If right child exists, put it in queue         // with current_level +1         if (p.first->right)             q.push({ p.first->right, p.second + 1 });     } } Â
// Stores Euler Tour int Euler[MAX]; Â
// index in Euler array int idx = 0; Â
// Find Euler Tour void eulerTree( struct Node* root) { Â
    // store current node's data     Euler[++idx] = root->data; Â
    // If left node exists     if (root->left) { Â
        // traverse left subtree         eulerTree(root->left); Â
        // store parent node's data         Euler[++idx] = root->data;     } Â
    // If right node exists     if (root->right) { Â
        // traverse right subtree         eulerTree(root->right); Â
        // store parent node's data         Euler[++idx] = root->data;     } } Â
// checks for visited nodes int vis[MAX]; Â
// Stores level of Euler Tour int L[MAX]; Â
// Stores indices of the first occurrence // of nodes in Euler tour int H[MAX]; Â
// Preprocessing Euler Tour for finding LCA void preprocessEuler( int size) { Â Â Â Â for ( int i = 1; i <= size; i++) { Â Â Â Â Â Â Â Â L[i] = level[Euler[i]]; Â
        // If node is not visited before         if (vis[Euler[i]] == 0) { Â
            // Add to first occurrence             H[Euler[i]] = i; Â
            // Mark it visited             vis[Euler[i]] = 1;         }     } } Â
// Sparse table of size [MAX][LOGMAX] // M[i][j] is the index of the minimum value in // the sub array starting at i having length 2^j int M[MAX][18]; Â
// Utility function to preprocess Sparse table void preprocessLCA( int N) { Â Â Â Â for ( int i = 0; i < N; i++) Â Â Â Â Â Â Â Â M[i][0] = i; Â
    for ( int j = 1; 1 << j <= N; j++)         for ( int i = 0; i + (1 << j) - 1 < N; i++)             if (L[M[i][j - 1]] < L[M[i + (1 << (j - 1))][j - 1]])                 M[i][j] = M[i][j - 1];             else                 M[i][j] = M[i + (1 << (j - 1))][j - 1]; } Â
// Utility function to find the index of the minimum // value in range a to b int LCA( int a, int b) {     // Subarray of length 2^j     int j = log2(b - a + 1);     if (L[M[a][j]] <= L[M[b - (1 << j) + 1][j]])         return M[a][j]; Â
    else         return M[b - (1 << j) + 1][j]; } Â
// Function to return distance between // two nodes n1 and n2 int findDistance( int n1, int n2) {     // Maintain original Values     int prevn1 = n1, prevn2 = n2; Â
    // Get First Occurrence of n1     n1 = H[n1]; Â
    // Get First Occurrence of n2     n2 = H[n2]; Â
    // Swap if low>high     if (n2 < n1)         swap(n1, n2); Â
    // Get position of minimum value     int lca = LCA(n1, n2); Â
    // Extract value out of Euler tour     lca = Euler[lca]; Â
    // return calculated distance     return level[prevn1] + level[prevn2] - 2 * level[lca]; } Â
void preProcessing(Node* root, int N) {     // Build Tree     eulerTree(root); Â
    // Store Levels     FindLevels(root); Â
    // Find L and H array     preprocessEuler(2 * N - 1); Â
    // Build sparse table     preprocessLCA(2 * N - 1); } Â
/* Driver function to test above functions */ int main() {     // Number of nodes     int N = 8; Â
    /* Constructing tree given in the above figure */     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->right->left->right = newNode(8); Â
    // Function to do all preprocessing     preProcessing(root, N); Â
    cout << "Dist(4, 5) = " << findDistance(4, 5) << "\n" ;     cout << "Dist(4, 6) = " << findDistance(4, 6) << "\n" ;     cout << "Dist(3, 4) = " << findDistance(3, 4) << "\n" ;     cout << "Dist(2, 4) = " << findDistance(2, 4) << "\n" ;     cout << "Dist(8, 5) = " << findDistance(8, 5) << "\n" ; Â
    return 0; } |
Java
// Java implementation of the approach import java.util.*; Â
class GFG { Â
    static class Pair<T, V> {         T first;         V second; Â
        Pair() {         } Â
        Pair(T first, V second) {             this .first = first;             this .second = second;         }     } Â
    static class Node {         int data;         Node left, right; Â
        Node( int data) {             this .data = data;             this .left = this .right = null ;         }     } Â
    static int MAX = 100001 ; Â
    // Array to store level of each node     static int [] level = new int [MAX]; Â
    // Utility Function to store level of all nodes     static void FindLevels(Node root) {         if (root == null )             return ; Â
        // queue to hold tree node with level         Queue<Pair<Node, Integer>> q = new LinkedList<>(); Â
        // let root node be at level 0         q.add( new Pair<>(root, 0 ));         Pair<Node, Integer> p = new Pair<>(); Â
        // Do level Order Traversal of tree         while (!q.isEmpty()) {             p = q.poll(); Â
            // Node p.first is on level p.second             level[p.first.data] = p.second; Â
            // If left child exits, put it in queue             // with current_level +1             if (p.first.left != null )                 q.add( new Pair<>(p.first.left, p.second + 1 )); Â
            // If right child exists, put it in queue             // with current_level +1             if (p.first.right != null )                 q.add( new Pair<>(p.first.right, p.second + 1 ));         }     } Â
    // Stores Euler Tour     static int [] Euler = new int [MAX]; Â
    // index in Euler array     static int idx = 0 ; Â
    // Find Euler Tour     static void eulerTree(Node root) { Â
        // store current node's data         Euler[++idx] = root.data; Â
        // If left node exists         if (root.left != null ) { Â
            // traverse left subtree             eulerTree(root.left); Â
            // store parent node's data             Euler[++idx] = root.data;         } Â
        // If right node exists         if (root.right != null ) { Â
            // traverse right subtree             eulerTree(root.right); Â
            // store parent node's data             Euler[++idx] = root.data;         }     } Â
    // checks for visited nodes     static int [] vis = new int [MAX]; Â
    // Stores level of Euler Tour     static int [] L = new int [MAX]; Â
    // Stores indices of the first occurrence     // of nodes in Euler tour     static int [] H = new int [MAX]; Â
    // Preprocessing Euler Tour for finding LCA     static void preprocessEuler( int size) {         for ( int i = 1 ; i <= size; i++) {             L[i] = level[Euler[i]]; Â
            // If node is not visited before             if (vis[Euler[i]] == 0 ) { Â
                // Add to first occurrence                 H[Euler[i]] = i; Â
                // Mark it visited                 vis[Euler[i]] = 1 ;             }         }     } Â
    // Sparse table of size [MAX][LOGMAX]     // M[i][j] is the index of the minimum value in     // the sub array starting at i having length 2^j     static int [][] M = new int [MAX][ 18 ]; Â
    // Utility function to preprocess Sparse table     static void preprocessLCA( int N) {         for ( int i = 0 ; i < N; i++)             M[i][ 0 ] = i; Â
        for ( int j = 1 ; 1 << j <= N; j++)             for ( int i = 0 ; i + ( 1 << j) - 1 < N; i++)                 if (L[M[i][j - 1 ]] < L[M[i + ( 1 << (j - 1 ))][j - 1 ]])                     M[i][j] = M[i][j - 1 ];                 else                     M[i][j] = M[i + ( 1 << (j - 1 ))][j - 1 ];     } Â
    // Utility function to find the index of the minimum     // value in range a to b     static int LCA( int a, int b) {         // Subarray of length 2^j         int j = ( int ) (Math.log(b - a + 1 ) / Math.log( 2 ));         if (L[M[a][j]] <= L[M[b - ( 1 << j) + 1 ][j]])             return M[a][j]; Â
        else             return M[b - ( 1 << j) + 1 ][j];     } Â
    // Function to return distance between     // two nodes n1 and n2     static int findDistance( int n1, int n2) {         // Maintain original Values         int prevn1 = n1, prevn2 = n2; Â
        // Get First Occurrence of n1         n1 = H[n1]; Â
        // Get First Occurrence of n2         n2 = H[n2]; Â
        // Swap if low>high         if (n2 < n1) {             int temp = n1;             n1 = n2;             n2 = temp;         } Â
        // Get position of minimum value         int lca = LCA(n1, n2); Â
        // Extract value out of Euler tour         lca = Euler[lca]; Â
        // return calculated distance         return level[prevn1] + level[prevn2] - 2 * level[lca];     } Â
    static void preProcessing(Node root, int N) {         // Build Tree         eulerTree(root); Â
        // Store Levels         FindLevels(root); Â
        // Find L and H array         preprocessEuler( 2 * N - 1 ); Â
        // Build sparse table         preprocessLCA( 2 * N - 1 );     } Â
    // Driver Code     public static void main(String[] args) {         // Number of nodes         int N = 8 ; Â
        /* Constructing tree given in the above figure */         Node root = new Node( 1 );         root.left = new Node( 2 );         root.right = new Node( 3 );         root.left.left = new Node( 4 );         root.left.right = new Node( 5 );         root.right.left = new Node( 6 );         root.right.right = new Node( 7 );         root.right.left.right = new Node( 8 ); Â
        // Function to do all preprocessing         preProcessing(root, N); Â
        System.out.println( "Dist(4, 5) = " + findDistance( 4 , 5 ));         System.out.println( "Dist(4, 6) = " + findDistance( 4 , 6 ));         System.out.println( "Dist(3, 4) = " + findDistance( 3 , 4 ));         System.out.println( "Dist(2, 4) = " + findDistance( 2 , 4 ));         System.out.println( "Dist(8, 5) = " + findDistance( 8 , 5 ));     } } Â
// This code is contributed by // sanjeev2552 |
Python3
from collections import deque from math import log2 Â
MAX = 100001 Â
# A tree node structure class Node:     def __init__( self , data):         self .data = data         self .left = None         self .right = None Â
# Array to store level of each node level = [ 0 ] * MAX Â
# Utility Function to store level of all nodes def findLevels(root: Node): Â Â Â Â global level Â
    if root is None :         return Â
    # queue to hold tree node with level     q = deque() Â
    # let root node be at level 0     q.append((root, 0 )) Â
    # Do level Order Traversal of tree     while q:         p = q[ 0 ]         q.popleft() Â
        # Node p.first is on level p.second         level[p[ 0 ].data] = p[ 1 ] Â
        # If left child exits, put it in queue         # with current_level +1         if p[ 0 ].left:             q.append((p[ 0 ].left, p[ 1 ] + 1 )) Â
        # If right child exists, put it in queue         # with current_level +1         if p[ 0 ].right:             q.append((p[ 0 ].right, p[ 1 ] + 1 )) Â
# Stores Euler Tour Euler = [ 0 ] * MAX Â
# index in Euler array idx = 0 Â
# Find Euler Tour def eulerTree(root: Node):     global Euler, idx     idx + = 1 Â
    # store current node's data     Euler[idx] = root.data Â
    # If left node exists     if root.left: Â
        # traverse left subtree         eulerTree(root.left)         idx + = 1 Â
        # store parent node's data         Euler[idx] = root.data Â
    # If right node exists     if root.right: Â
        # traverse right subtree         eulerTree(root.right)         idx + = 1 Â
        # store parent node's data         Euler[idx] = root.data Â
# checks for visited nodes vis = [ 0 ] * MAX Â
# Stores level of Euler Tour L = [ 0 ] * MAX Â
# Stores indices of the first occurrence # of nodes in Euler tour H = [ 0 ] * MAX Â
# Preprocessing Euler Tour for finding LCA def preprocessEuler(size: int ):     global L, H, vis     for i in range ( 1 , size + 1 ):         L[i] = level[Euler[i]] Â
        # If node is not visited before         if vis[Euler[i]] = = 0 : Â
            # Add to first occurrence             H[Euler[i]] = i Â
            # Mark it visited             vis[Euler[i]] = 1 Â
# Sparse table of size [MAX][LOGMAX] # M[i][j] is the index of the minimum value in # the sub array starting at i having length 2^j M = [[ 0 for i in range ( 18 )] for j in range ( MAX )] Â
# Utility function to preprocess Sparse table def preprocessLCA(N: int ): Â Â Â Â global M Â Â Â Â for i in range (N): Â Â Â Â Â Â Â Â M[i][ 0 ] = i Â
    j = 1     while 1 << j < = N:         i = 0         while i + ( 1 << j) - 1 < N:             if L[M[i][j - 1 ]] < L[M[i +                 ( 1 << (j - 1 ))][j - 1 ]]:                 M[i][j] = M[i][j - 1 ]             else :                 M[i][j] = M[i + ( 1 << (j - 1 ))][j - 1 ]             i + = 1         j + = 1 Â
# Utility function to find the index of the minimum # value in range a to b def LCA(a: int , b: int ) - > int : Â
    # Subarray of length 2^j     j = int (log2(b - a + 1 ))     if L[M[a][j]] < = L[M[b - ( 1 << j) + 1 ][j]]:         return M[a][j]     else :         return M[b - ( 1 << j) + 1 ][j] Â
# Function to return distance between # two nodes n1 and n2 def findDistance(n1: int , n2: int ) - > int : Â
    # Maintain original Values     prevn1 = n1     prevn2 = n2 Â
    # Get First Occurrence of n1     n1 = H[n1] Â
    # Get First Occurrence of n2     n2 = H[n2] Â
    # Swap if low>high     if n2 < n1:         n1, n2 = n2, n1 Â
    # Get position of minimum value     lca = LCA(n1, n2) Â
    # Extract value out of Euler tour     lca = Euler[lca] Â
    # return calculated distance     return level[prevn1] + level[prevn2] - 2 * level[lca] Â
def preProcessing(root: Node, N: int ): Â
    # Build Tree     eulerTree(root) Â
    # Store Levels     findLevels(root) Â
    # Find L and H array     preprocessEuler( 2 * N - 1 ) Â
    # Build sparse table     preprocessLCA( 2 * N - 1 ) Â
# Driver Code if __name__ = = "__main__" : Â
    # Number of nodes     N = 8 Â
    # Constructing tree given in the above figure     root = Node( 1 )     root.left = Node( 2 )     root.right = Node( 3 )     root.left.left = Node( 4 )     root.left.right = Node( 5 )     root.right.left = Node( 6 )     root.right.right = Node( 7 )     root.right.left.right = Node( 8 ) Â
    # Function to do all preprocessing     preProcessing(root, N) Â
    print ( "Dist(4, 5) =" , findDistance( 4 , 5 ))     print ( "Dist(4, 6) =" , findDistance( 4 , 6 ))     print ( "Dist(3, 4) =" , findDistance( 3 , 4 ))     print ( "Dist(2, 4) =" , findDistance( 2 , 4 ))     print ( "Dist(8, 5) =" , findDistance( 8 , 5 )) Â
# This code is contributed by # sanjeev2552 |
C#
// C# implementation of the approach using System; using System.Collections.Generic; Â
public class GFG {   public     class Pair<T, V>     {       public         T first;       public         V second;       public         Pair() {       } Â
      public         Pair(T first, V second)       {         this .first = first;         this .second = second;       }     }   public     class Node     {       public         int data;       public         Node left, right;       public         Node( int data)       {         this .data = data;         this .left = this .right = null ;       }     }   static int MAX = 100001; Â
  // Array to store level of each node   static int [] level = new int [MAX]; Â
  // Utility Function to store level of all nodes   static void FindLevels(Node root)   {     if (root == null )       return ; Â
    // queue to hold tree node with level     Queue<Pair<Node, int >> q = new Queue<Pair<Node, int >>(); Â
    // let root node be at level 0     q.Enqueue( new Pair<Node, int >(root, 0));     Pair<Node, int > p = new Pair<Node, int >(); Â
    // Do level Order Traversal of tree     while (q.Count != 0)     {       p = q.Peek();       q.Dequeue(); Â
      // Node p.first is on level p.second       level[p.first.data] = p.second; Â
      // If left child exits, put it in queue       // with current_level +1       if (p.first.left != null )         q.Enqueue( new Pair<Node, int >(p.first.left, p.second + 1)); Â
      // If right child exists, put it in queue       // with current_level +1       if (p.first.right != null )         q.Enqueue( new Pair<Node, int >(p.first.right, p.second + 1));     }   } Â
  // Stores Euler Tour   static int [] Euler = new int [MAX]; Â
  // index in Euler array   static int idx = 0; Â
  // Find Euler Tour   static void eulerTree(Node root)   { Â
    // store current node's data     Euler[++idx] = root.data; Â
    // If left node exists     if (root.left != null )     { Â
      // traverse left subtree       eulerTree(root.left); Â
      // store parent node's data       Euler[++idx] = root.data;     } Â
    // If right node exists     if (root.right != null )     { Â
      // traverse right subtree       eulerTree(root.right); Â
      // store parent node's data       Euler[++idx] = root.data;     }   } Â
  // checks for visited nodes   static int [] vis = new int [MAX]; Â
  // Stores level of Euler Tour   static int [] L = new int [MAX]; Â
  // Stores indices of the first occurrence   // of nodes in Euler tour   static int [] H = new int [MAX]; Â
  // Preprocessing Euler Tour for finding LCA   static void preprocessEuler( int size) {     for ( int i = 1; i <= size; i++) {       L[i] = level[Euler[i]]; Â
      // If node is not visited before       if (vis[Euler[i]] == 0)       { Â
        // Add to first occurrence         H[Euler[i]] = i; Â
        // Mark it visited         vis[Euler[i]] = 1;       }     }   } Â
  // Sparse table of size [MAX,LOGMAX]   // M[i,j] is the index of the minimum value in   // the sub array starting at i having length 2^j   static int [,] M = new int [MAX, 18]; Â
  // Utility function to preprocess Sparse table   static void preprocessLCA( int N)   {     for ( int i = 0; i < N; i++)       M[i, 0] = i;     for ( int j = 1; 1 << j <= N; j++)       for ( int i = 0; i + (1 << j) - 1 < N; i++)         if (L[M[i, j - 1]] < L[M[i + (1 << (j - 1)), j - 1]])           M[i, j] = M[i, j - 1];     else       M[i, j] = M[i + (1 << (j - 1)), j - 1];   } Â
  // Utility function to find the index of the minimum   // value in range a to b   static int LCA( int a, int b)   { Â
    // Subarray of length 2^j     int j = ( int ) (Math.Log(b - a + 1) / Math.Log(2));     if (L[M[a,j]] <= L[M[b - (1 << j) + 1,j]])       return M[a,j]; Â
    else       return M[b - (1 << j) + 1,j];   } Â
  // Function to return distance between   // two nodes n1 and n2   static int findDistance( int n1, int n2) {     // Maintain original Values     int prevn1 = n1, prevn2 = n2; Â
    // Get First Occurrence of n1     n1 = H[n1]; Â
    // Get First Occurrence of n2     n2 = H[n2]; Â
    // Swap if low>high     if (n2 < n1)     {       int temp = n1;       n1 = n2;       n2 = temp;     } Â
    // Get position of minimum value     int lca = LCA(n1, n2); Â
    // Extract value out of Euler tour     lca = Euler[lca]; Â
    // return calculated distance     return level[prevn1] + level[prevn2] - 2 * level[lca];   } Â
  static void preProcessing(Node root, int N)   { Â
    // Build Tree     eulerTree(root); Â
    // Store Levels     FindLevels(root); Â
    // Find L and H array     preprocessEuler(2 * N - 1); Â
    // Build sparse table     preprocessLCA(2 * N - 1);   } Â
  // Driver Code   public static void Main(String[] args)   { Â
    // Number of nodes     int N = 8; Â
    /* Constructing tree given in the above figure */     Node root = new Node(1);     root.left = new Node(2);     root.right = new Node(3);     root.left.left = new Node(4);     root.left.right = new Node(5);     root.right.left = new Node(6);     root.right.right = new Node(7);     root.right.left.right = new Node(8); Â
    // Function to do all preprocessing     preProcessing(root, N); Â
    Console.WriteLine( "Dist(4, 5) = " + findDistance(4, 5));     Console.WriteLine( "Dist(4, 6) = " + findDistance(4, 6));     Console.WriteLine( "Dist(3, 4) = " + findDistance(3, 4));     Console.WriteLine( "Dist(2, 4) = " + findDistance(2, 4));     Console.WriteLine( "Dist(8, 5) = " + findDistance(8, 5));   } } Â
// This code is contributed by aashish1995 |
Javascript
<script> // Javascript implementation of the approach Â
class Pair{ Â Â Â Â constructor(first, second) Â Â Â Â { Â Â Â Â Â Â Â Â this .first = first; Â Â Â Â Â Â Â Â this .second = second; Â Â Â Â } } Â
class Node{ Â Â Â Â constructor(data) Â Â Â Â { Â Â Â Â Â Â Â Â this .data = data; Â Â Â Â Â Â Â Â this .left = null ; Â Â Â Â Â Â Â Â this .right = null ; Â Â Â Â } } Â
var MAX = 100001; Â
// Array to store level of each node var level = Array(MAX); Â
// Utility Function to store level of all nodes function FindLevels(root) {   if (root == null )     return ;        // queue to hold tree node with level   var q = [];      // let root node be at level 0   q.push( new Pair(root, 0));   var p = new Pair();      // Do level Order Traversal of tree   while (q.length != 0)   {     p = q[0];     q.shift();          // Node p.first is on level p.second     level[p.first.data] = p.second;          // If left child exits, put it in queue     // with current_level +1     if (p.first.left != null )       q.push( new Pair(p.first.left, p.second + 1));            // If right child exists, put it in queue     // with current_level +1     if (p.first.right != null )       q.push( new Pair(p.first.right, p.second + 1));   } } // Stores Euler Tour var Euler = Array(MAX); Â
// index in Euler array var idx = 0; Â
// Find Euler Tour function eulerTree(root) { Â
  // store current node's data   Euler[++idx] = root.data;      // If left node exists   if (root.left != null )   {        // traverse left subtree     eulerTree(root.left);          // store parent node's data     Euler[++idx] = root.data;   }      // If right node exists   if (root.right != null )   {        // traverse right subtree     eulerTree(root.right);          // store parent node's data     Euler[++idx] = root.data;   } } Â
// checks for visited nodes var vis = Array(MAX).fill(0); Â
// Stores level of Euler Tour var L = Array(MAX).fill(0); Â
// Stores indices of the first occurrence // of nodes in Euler tour var H = Array(MAX).fill(0); Â
// Preprocessing Euler Tour for finding LCA function preprocessEuler(size) {   for ( var i = 1; i <= size; i++)   {     L[i] = level[Euler[i]];          // If node is not visited before     if (vis[Euler[i]] == 0)     {            // Add to first occurrence       H[Euler[i]] = i;              // Mark it visited       vis[Euler[i]] = 1;     }   } } Â
// Sparse table of size [MAX,LOGMAX] // M[i,j] is the index of the minimum value in // the sub array starting at i having length 2^j var M = Array.from(Array(MAX), ()=>Array(18)); Â
// Utility function to preprocess Sparse table function preprocessLCA(N) {   for ( var i = 0; i < N; i++)     M[i][0] = i;   for ( var j = 1; 1 << j <= N; j++)     for ( var i = 0; i + (1 << j) - 1 < N; i++)       if (L[M[i][j - 1]] < L[M[i + (1 << (j - 1))][j - 1]])         M[i][j] = M[i][j - 1];   else     M[i][j] = M[i + (1 << (j - 1))][j - 1]; } Â
// Utility function to find the index of the minimum // value in range a to b function LCA(a, b) { Â
  // Subarray of length 2^j   var j = parseInt(Math.log(b - a + 1) / Math.log(2));   if (L[M[a][j]] <= L[M[b - (1 << j) + 1][j]])     return M[a][j];   else     return M[b - (1 << j) + 1][j]; } Â
// Function to return distance between // two nodes n1 and n2 function findDistance( n1, n2) { Â
  // Maintain original Values   var prevn1 = n1, prevn2 = n2;      // Get First Occurrence of n1   n1 = H[n1];      // Get First Occurrence of n2   n2 = H[n2];      // Swap if low>high   if (n2 < n1)   {     var temp = n1;     n1 = n2;     n2 = temp;   }   // Get position of minimum value   var lca = LCA(n1, n2);      // Extract value out of Euler tour   lca = Euler[lca];      // return calculated distance   return level[prevn1] + level[prevn2] - 2 * level[lca]; } Â
function preProcessing(root, N) {   // Build Tree   eulerTree(root);      // Store Levels   FindLevels(root);      // Find L and H array   preprocessEuler(2 * N - 1);      // Build sparse table   preprocessLCA(2 * N - 1); } Â
// Driver Code // Number of nodes var N = 8; Â
/* Constructing tree given in the above figure */ var root = new Node(1); root.left = new Node(2); root.right = new Node(3); root.left.left = new Node(4); root.left.right = new Node(5); root.right.left = new Node(6); root.right.right = new Node(7); root.right.left.right = new Node(8); Â
// Function to do all preprocessing preProcessing(root, N); document.write( "Dist(4, 5) = " + findDistance(4, 5) + "<br>" ); document.write( "Dist(4, 6) = " + findDistance(4, 6) + "<br>" ); document.write( "Dist(3, 4) = " + findDistance(3, 4) + "<br>" ); document.write( "Dist(2, 4) = " + findDistance(2, 4) + "<br>" ); document.write( "Dist(8, 5) = " + findDistance(8, 5) + "<br>" ); Â
// This code is contributed by itsok. </script> |
Dist(4, 5) = 2 Dist(4, 6) = 4 Dist(3, 4) = 3 Dist(2, 4) = 1 Dist(8, 5) = 5
Complexity Analysis:
- Time Complexity: O(N log N)Â
- Space Complexity: O(N log N)Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!