GeeksforGeeks App
Open App
Browser
Continue

# LCA in a tree using Binary Lifting Technique

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 the 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 then that particular node is the LCA of those two nodes. In particular, if we want to find the LCA of u and v, and if u is a parent of v, then u is their lowest common ancestor.

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][0] (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 another or not and if one node is ancestor of another then it is the LCA of these two nodes otherwise we find a node that is not the common ancestor of both u and v and is the highest(i.e. a node x such that x is not the common ancestor of u and v but memo[x][0] is) in the tree. After finding such a node (let it be x), we print the first ancestor of x i.e. memo[x][0] 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, vector<``int``> &lev, ``int` `log``, vector<``int``> *g)``{``    ``// 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)``        ``{``            ``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``, vector<``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][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``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``    ``vector<``int``> lev(n + 1);` `    ``// Initialising memo values with -1``    ``for` `(``int` `i = 0; i <= n; i++)``        ``memset``(memo[i], -1, ``sizeof` `memo[i]);` `    ``// Add edges``    ``g[1].push_back(2);``    ``g[2].push_back(1);``    ``g[1].push_back(3);``    ``g[3].push_back(1);``    ``g[1].push_back(4);``    ``g[4].push_back(1);``    ``g[2].push_back(5);``    ``g[5].push_back(2);``    ``g[3].push_back(6);``    ``g[6].push_back(3);``    ``g[3].push_back(7);``    ``g[7].push_back(3);``    ``g[3].push_back(8);``    ``g[8].push_back(3);``    ``g[4].push_back(9);``    ``g[9].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][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` `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][0] 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[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);``        ``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