# LCA in a tree using Binary Lifting Technique

• Difficulty Level : Hard
• Last Updated : 04 Sep, 2021

Given a binary tree, the task is to find the Lowest Common Ancestor of the given two nodes in the tree.
Let G be a tree then LCA of two nodes u and v is defined as the node w in the tree which is an ancestor of both u and v and is farthest from the root node.If one node is the ancestor of another one than that particular node is the LCA of those two nodes.
Example:

Input: Output:
The LCA of 6 and 9 is 1.
The LCA of 5 and 9 is 1.
The LCA of 6 and 8 is 3.
The LCA of 6 and 1 is 1.

Approach: The article describes an approach known as Binary Lifting to find the Lowest Common Ancestor of two nodes in a tree. There can be many approaches to solve the LCA problem. We are discussing the Binary Lifting Technique, the others can be read from here and here
Binary Lifting is a dynamic programming approach where we pre-compute an array memo[1, n][1, log(n)] where memo[i][j] contains 2^j-th ancestor of node i. For computing the values of memo[][], the following recursion may be used

memo state:

memo[i][j] = i-th node’s 2^(j)th ancestor in the path

memo initialization:

memo[i][j] = memo[i] (first parent (2^0) of each node is given)

memo trans:

memo[i][j] = memo[ memo [i][j – 1]]

meaning: A(i,2^j)=A( A(i , 2^(j-1) ) , 2^(j-1) )

To find the (2^j)-th ancestor of i, recursively find i-th node’s 2^(j-1)th ancestor’s 2^(j-1)th ancestor. (2^(j) = 2^(j-1) + 2^(j-1))

So:

memo[i][j] = parent[i] if j = 0 and
memo[i][j] = memo[memo[i][j – 1]][j – 1] if j > 0.

We first check whether a node is an ancestor of other or not and if one node is ancestor of other then it is the LCA of these two nodes otherwise we find a node which is not the common ancestor of both u and v and is highest(i.e. a node x such that x is not the common ancestor of u and v but memo[x] is) in the tree. After finding such a node (let it be x), we print the first ancestor of x i.e. memo[x] which will be the required LCA.
Below is the implementation of the above approach:

## C++

 `// C++ implementation of the approach``#include ``using` `namespace` `std;` `// Pre-processing to calculate values of memo[][]``void` `dfs(``int` `u, ``int` `p, ``int` `**memo, ``int` `*lev, ``int` `log``, vector<``int``> *g)``{``    ``// Using recursion formula to calculate``    ``// the values of memo[][]``    ``memo[u] = p;``    ``for` `(``int` `i = 1; i <= ``log``; i++)``        ``memo[u][i] = memo[memo[u][i - 1]][i - 1];``    ``for` `(``int` `v : g[u])``    ``{``        ``if` `(v != p)``        ``{``            ``lev[v] = lev[u] + 1;``            ``dfs(v, u, memo, lev, ``log``, g);``        ``}``    ``}``}` `// Function to return the LCA of nodes u and v``int` `lca(``int` `u, ``int` `v, ``int` `log``, ``int` `*lev, ``int` `**memo)``{``    ``// The node which is present farthest``    ``// from the root node is taken as u``    ``// If v is farther from root node``    ``// then swap the two``    ``if` `(lev[u] < lev[v])``        ``swap(u, v);` `    ``// Finding the ancestor of u``    ``// which is at same level as v``    ``for` `(``int` `i = ``log``; i >= 0; i--)``        ``if` `((lev[u] - ``pow``(2, i)) >= lev[v])``            ``u = memo[u][i];` `    ``// If v is the ancestor of u``    ``// then v is the LCA of u and v``    ``if` `(u == v)``        ``return` `u;` `    ``// Finding the node closest to the root which is``    ``// not the common ancestor of u and v i.e. a node``    ``// x such that x is not the common ancestor of u``    ``// and v but memo[x] is``    ``for` `(``int` `i = ``log``; i >= 0; i--)``    ``{``        ``if` `(memo[u][i] != memo[v][i])``        ``{``            ``u = memo[u][i];``            ``v = memo[v][i];``        ``}``    ``}` `    ``// Returning the first ancestor``    ``// of above found node``    ``return` `memo[u];``}` `// Driver Code``int` `main()``{``    ``// Number of nodes``    ``int` `n = 9;` `    ``// vector to store tree``    ``vector<``int``> g[n + 1];` `    ``int` `log` `= (``int``)``ceil``(log2(n));``    ``int` `**memo = ``new` `int` `*[n + 1];``    ``for` `(``int` `i = 0; i < n + 1; i++)``        ``memo[i] = ``new` `int``[``log` `+ 1];` `    ``// Stores the level of each node``    ``int` `*lev = ``new` `int``[n + 1];` `    ``// Initialising memo values with -1``    ``for` `(``int` `i = 0; i <= n; i++)``        ``memset``(memo[i], -1, ``sizeof` `memo[i]);` `    ``// Add edges``    ``g.push_back(2);``    ``g.push_back(1);``    ``g.push_back(3);``    ``g.push_back(1);``    ``g.push_back(4);``    ``g.push_back(1);``    ``g.push_back(5);``    ``g.push_back(2);``    ``g.push_back(6);``    ``g.push_back(3);``    ``g.push_back(7);``    ``g.push_back(3);``    ``g.push_back(8);``    ``g.push_back(3);``    ``g.push_back(9);``    ``g.push_back(4);``    ``dfs(1, 1, memo, lev, ``log``, g);``    ``cout << ``"The LCA of 6 and 9 is "` `<< lca(6, 9, ``log``, lev, memo) << endl;``    ``cout << ``"The LCA of 5 and 9 is "` `<< lca(5, 9, ``log``, lev, memo) << endl;``    ``cout << ``"The LCA of 6 and 8 is "` `<< lca(6, 8, ``log``, lev, memo) << endl;``    ``cout << ``"The LCA of 6 and 1 is "` `<< lca(6, 1, ``log``, lev, memo) << endl;` `    ``return` `0;``}` `// This code is contributed by``// sanjeev2552`

## Java

 `// Java implementation of the approach``import` `java.util.*;``public` `class` `GFG {` `    ``// ArrayList to store tree``    ``static` `ArrayList g[];``    ``static` `int` `memo[][], lev[], log;` `    ``// Pre-processing to calculate values of memo[][]``    ``static` `void` `dfs(``int` `u, ``int` `p)``    ``{` `        ``// Using recursion formula to calculate``        ``// the values of memo[][]``        ``memo[u][``0``] = p;``        ``for` `(``int` `i = ``1``; i <= log; i++)``            ``memo[u][i] = memo[memo[u][i - ``1``]][i - ``1``];``        ``for` `(``int` `v : g[u]) {``            ``if` `(v != p) {` `                ``// Calculating the level of each node``                ``lev[v] = lev[u] + ``1``;``                ``dfs(v, u);``            ``}``        ``}``    ``}` `    ``// Function to return the LCA of nodes u and v``    ``static` `int` `lca(``int` `u, ``int` `v)``    ``{``        ``// The node which is present farthest``        ``// from the root node is taken as u``        ``// If v is farther from root node``        ``// then swap the two``        ``if` `(lev[u] < lev[v]) {``            ``int` `temp = u;``            ``u = v;``            ``v = temp;``        ``}` `        ``// Finding the ancestor of u``        ``// which is at same level as v``        ``for` `(``int` `i = log; i >= ``0``; i--) {``            ``if` `((lev[u] - (``int``)Math.pow(``2``, i)) >= lev[v])``                ``u = memo[u][i];``        ``}` `        ``// If v is the ancestor of u``        ``// then v is the LCA of u and v``        ``if` `(u == v)``            ``return` `u;` `        ``// Finding the node closest to the root which is``        ``// not the common ancestor of u and v i.e. a node``        ``// x such that x is not the common ancestor of u``        ``// and v but memo[x] is``        ``for` `(``int` `i = log; i >= ``0``; i--) {``            ``if` `(memo[u][i] != memo[v][i]) {``                ``u = memo[u][i];``                ``v = memo[v][i];``            ``}``        ``}` `        ``// Returning the first ancestor``        ``// of above found node``        ``return` `memo[u][``0``];``    ``}` `    ``// Driver code``    ``public` `static` `void` `main(String args[])``    ``{` `        ``// Number of nodes``        ``int` `n = ``9``;``        ``g = ``new` `ArrayList[n + ``1``];` `        ``// log(n) with base 2``        ``log = (``int``)Math.ceil(Math.log(n) / Math.log(``2``));``        ``memo = ``new` `int``[n + ``1``][log + ``1``];` `        ``// Stores the level of each node``        ``lev = ``new` `int``[n + ``1``];` `        ``// Initialising memo values with -1``        ``for` `(``int` `i = ``0``; i <= n; i++)``            ``Arrays.fill(memo[i], -``1``);``        ``for` `(``int` `i = ``0``; i <= n; i++)``            ``g[i] = ``new` `ArrayList<>();` `        ``// Add edges``        ``g[``1``].add(``2``);``        ``g[``2``].add(``1``);``        ``g[``1``].add(``3``);``        ``g[``3``].add(``1``);``        ``g[``1``].add(``4``);``        ``g[``4``].add(``1``);``        ``g[``2``].add(``5``);``        ``g[``5``].add(``2``);``        ``g[``3``].add(``6``);``        ``g[``6``].add(``3``);``        ``g[``3``].add(``7``);``        ``g[``7``].add(``3``);``        ``g[``3``].add(``8``);``        ``g[``8``].add(``3``);``        ``g[``4``].add(``9``);``        ``g[``9``].add(``4``);``        ``dfs(``1``, ``1``);``        ``System.out.println(``"The LCA of 6 and 9 is "` `+ lca(``6``, ``9``));``        ``System.out.println(``"The LCA of 5 and 9 is "` `+ lca(``5``, ``9``));``        ``System.out.println(``"The LCA of 6 and 8 is "` `+ lca(``6``, ``8``));``        ``System.out.println(``"The LCA of 6 and 1 is "` `+ lca(``6``, ``1``));``    ``}``}`

## Python3

 `# Python3 implementation of the above approach``import` `math` `# Pre-processing to calculate values of memo[][]``def` `dfs(u, p, memo, lev, log, g):``    ` `    ``# Using recursion formula to calculate``    ``# the values of memo[][]``    ``memo[u][``0``] ``=` `p``    ``for` `i ``in` `range``(``1``, log ``+` `1``):``        ``memo[u][i] ``=` `memo[memo[u][i ``-` `1``]][i ``-` `1``]``        ` `    ``for` `v ``in` `g[u]:``        ``if` `v !``=` `p:``            ``lev[v] ``=` `lev[u] ``+` `1``            ``dfs(v, u, memo, lev, log, g)` `# Function to return the LCA of nodes u and v``def` `lca(u, v, log, lev, memo):``    ` `    ``# The node which is present farthest``    ``# from the root node is taken as u``    ``# If v is farther from root node``    ``# then swap the two``    ``if` `lev[u] < lev[v]:``        ``swap(u, v)``        ` `    ``# Finding the ancestor of u``    ``# which is at same level as v``    ``for` `i ``in` `range``(log, ``-``1``, ``-``1``):``        ``if` `(lev[u] ``-` `pow``(``2``, i)) >``=` `lev[v]:``            ``u ``=` `memo[u][i]``            ` `    ``# If v is the ancestor of u``    ``# then v is the LCA of u and v        ``    ``if` `u ``=``=` `v:``        ``return` `v``        ` `    ``# Finding the node closest to the``    ``# root which is not the common ancestor``    ``# of u and v i.e. a node x such that x``    ``# is not the common ancestor of u``    ``# and v but memo[x] is``    ``for` `i ``in` `range``(log, ``-``1``, ``-``1``):``        ``if` `memo[u][i] !``=` `memo[v][i]:``            ``u ``=` `memo[u][i]``            ``v ``=` `memo[v][i]``    ` `    ``# Returning the first ancestor``    ``# of above found node        ``    ``return` `memo[u][``0``]` `# Driver code` `# Number of nodes``n ``=` `9` `log ``=` `math.ceil(math.log(n, ``2``))``g ``=` `[[] ``for` `i ``in` `range``(n ``+` `1``)]` `memo ``=` `[[``-``1` `for` `i ``in` `range``(log ``+` `1``)]``            ``for` `j ``in` `range``(n ``+` `1``)]` `# Stores the level of each node            ``lev ``=` `[``0` `for` `i ``in` `range``(n ``+` `1``)]` `# Add edges``g[``1``].append(``2``)``g[``2``].append(``1``)``g[``1``].append(``3``)``g[``3``].append(``1``)``g[``1``].append(``4``)``g[``4``].append(``1``)``g[``2``].append(``5``)``g[``5``].append(``2``)``g[``3``].append(``6``)``g[``6``].append(``3``)``g[``3``].append(``7``)``g[``7``].append(``3``)``g[``3``].append(``8``)``g[``8``].append(``3``)``g[``4``].append(``9``)``g[``9``].append(``4``)` `dfs(``1``, ``1``, memo, lev, log, g)` `print``(``"The LCA of 6 and 9 is"``, lca(``6``, ``9``, log, lev, memo))``print``(``"The LCA of 5 and 9 is"``, lca(``5``, ``9``, log, lev, memo))``print``(``"The LCA of 6 and 8 is"``, lca(``6``, ``8``, log, lev, memo))``print``(``"The LCA of 6 and 1 is"``, lca(``6``, ``1``, log, lev, memo))` `# This code is contributed by Bhaskar`

## C#

 `// C# implementation of the approach``using` `System;``using` `System.Collections.Generic;` `class` `GFG``{` `    ``// List to store tree``    ``static` `List<``int``> []g;``    ``static` `int` `[,]memo;``    ``static` `int` `[]lev;``    ``static` `int` `log;` `    ``// Pre-processing to calculate``    ``// values of memo[,]``    ``static` `void` `dfs(``int` `u, ``int` `p)``    ``{` `        ``// Using recursion formula to``        ``// calculate the values of memo[,]``        ``memo[u, 0] = p;``        ``for` `(``int` `i = 1; i <= log; i++)``            ``memo[u, i] = memo[memo[u, i - 1],``                                    ``i - 1];``        ``foreach` `(``int` `v ``in` `g[u])``        ``{``            ``if` `(v != p)``            ``{` `                ``// Calculating the level of each node``                ``lev[v] = lev[u] + 1;``                ``dfs(v, u);``            ``}``        ``}``    ``}` `    ``// Function to return the LCA of``    ``// nodes u and v``    ``static` `int` `lca(``int` `u, ``int` `v)``    ``{``        ``// The node which is present farthest``        ``// from the root node is taken as u``        ``// If v is farther from root node``        ``// then swap the two``        ``if` `(lev[u] < lev[v])``        ``{``            ``int` `temp = u;``            ``u = v;``            ``v = temp;``        ``}` `        ``// Finding the ancestor of u``        ``// which is at same level as v``        ``for` `(``int` `i = log; i >= 0; i--)``        ``{``            ``if` `((lev[u] - (``int``)Math.Pow(2, i)) >= lev[v])``                ``u = memo[u, i];``        ``}` `        ``// If v is the ancestor of u``        ``// then v is the LCA of u and v``        ``if` `(u == v)``            ``return` `u;` `        ``// Finding the node closest to the root``        ``// which is not the common ancestor of``        ``// u and v i.e. a node x such that``        ``// x is not the common ancestor of u``        ``// and v but memo[x,0] is``        ``for` `(``int` `i = log; i >= 0; i--)``        ``{``            ``if` `(memo[u, i] != memo[v, i])``            ``{``                ``u = memo[u, i];``                ``v = memo[v, i];``            ``}``        ``}` `        ``// Returning the first ancestor``        ``// of above found node``        ``return` `memo[u, 0];``    ``}` `    ``// Driver code``    ``public` `static` `void` `Main(String []args)``    ``{` `        ``// Number of nodes``        ``int` `n = 9;``        ``g = ``new` `List<``int``>[n + 1];` `        ``// log(n) with base 2``        ``log = (``int``)Math.Ceiling(Math.Log(n) / Math.Log(2));``        ``memo = ``new` `int``[n + 1, log + 1];` `        ``// Stores the level of each node``        ``lev = ``new` `int``[n + 1];` `        ``// Initialising memo values with -1``        ``for` `(``int` `i = 0; i <= n; i++)``            ``for` `(``int` `j = 0; j <= log; j++)``                ``memo[i, j] = -1;``        ``for` `(``int` `i = 0; i <= n; i++)``            ``g[i] = ``new` `List<``int``>();` `        ``// Add edges``        ``g.Add(2);``        ``g.Add(1);``        ``g.Add(3);``        ``g.Add(1);``        ``g.Add(4);``        ``g.Add(1);``        ``g.Add(5);``        ``g.Add(2);``        ``g.Add(6);``        ``g.Add(3);``        ``g.Add(7);``        ``g.Add(3);``        ``g.Add(8);``        ``g.Add(3);``        ``g.Add(9);``        ``g.Add(4);``        ``dfs(1, 1);``        ``Console.WriteLine(``"The LCA of 6 and 9 is "` `+``                                        ``lca(6, 9));``        ``Console.WriteLine(``"The LCA of 5 and 9 is "` `+``                                        ``lca(5, 9));``        ``Console.WriteLine(``"The LCA of 6 and 8 is "` `+``                                        ``lca(6, 8));``        ``Console.WriteLine(``"The LCA of 6 and 1 is "` `+``                                        ``lca(6, 1));``    ``}``}` `// This code is contributed by PrinciRaj1992`

## Javascript

 ``
Output:
```The LCA of 6 and 9 is 1
The LCA of 5 and 9 is 1
The LCA of 6 and 8 is 3
The LCA of 6 and 1 is 1```

Time Complexity: The time taken in pre-processing is O(NlogN) and every query takes O(logN) time. So the overall time complexity of the solution is O(NlogN).
Auxiliary Space: O(NlogN)

My Personal Notes arrow_drop_up