 Open in App
Not now

# LCA in a tree using Binary Lifting Technique

• Difficulty Level : Hard
• Last Updated : 07 Dec, 2022

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, vector<``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``, 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] 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 ` `    ``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.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
Related Articles