GFG App
Open App
Browser
Continue

# LCA for general or n-ary trees (Sparse Matrix DP approach )

In previous posts, we have discussed how to calculate the Lowest Common Ancestor (LCA) for a binary tree and a binary search tree (this, this and this). Now let’s look at a method that can calculate LCA for any tree (not only for binary tree). We use Dynamic Programming with Sparse Matrix Approach in our method. This method is very handy and fast when you need to answer multiple queries of LCA for a tree.

Pre-requisites:

1. DFS
2. Basic DP knowledge (This and this
3. Range Minimum Query (Square Root Decomposition and Sparse Table)

Naive Approach:- O(n)
The naive approach for this general tree LCA calculation will be the same as the naive approach for the LCA calculation of Binary Tree (this naive approach is already well described here.

The implementation for the naive approach is given below:-

## C++

 `/* Program to find LCA of n1 and n2 using one DFS on` `   ``the Tree */` `#include` `using` `namespace` `std;`   `// Maximum number of nodes is 100000 and nodes are` `// numbered from 1 to 100000` `#define MAXN 100001`   `vector < ``int` `> tree[MAXN];` `int` `path[3][MAXN]; ``// storing root to node path`   `// storing the path from root to node` `void` `dfs(``int` `cur, ``int` `prev, ``int` `pathNumber, ``int` `ptr,` `                             ``int` `node, ``bool` `&flag)` `{` `    ``for` `(``int` `i=0; i

## Java

 `/* Program to find LCA of n1 and n2 using one DFS on` `the Tree */`   `import` `java.util.*;`   `class` `GFG ` `{`   `    ``// Maximum number of nodes is 100000 and nodes are` `    ``// numbered from 1 to 100000` `    ``static` `final` `int` `MAXN = ``100001``;`   `    ``static` `Vector[] tree = ``new` `Vector[MAXN];` `    ``static` `int``[][] path = ``new` `int``[``3``][MAXN]; ``// storing root to node path` `    ``static` `boolean` `flag;`   `    ``// storing the path from root to node` `    ``static` `void` `dfs(``int` `cur, ``int` `prev, ``int` `pathNumber, ``int` `ptr, ``int` `node) ` `    ``{` `        ``for` `(``int` `i = ``0``; i < tree[cur].size(); i++) ` `        ``{` `            ``if` `(tree[cur].get(i) != prev && !flag)` `            ``{` `                ``// pushing current node into the path` `                ``path[pathNumber][ptr] = tree[cur].get(i);` `                ``if` `(tree[cur].get(i) == node) ` `                ``{` `                    ``// node found` `                    ``flag = ``true``;`   `                    ``// terminating the path` `                    ``path[pathNumber][ptr + ``1``] = -``1``;` `                    ``return``;` `                ``}` `                ``dfs(tree[cur].get(i), cur, pathNumber, ptr + ``1``, node);` `            ``}` `        ``}` `    ``}`   `    ``// This Function compares the path from root to 'a' & root` `    ``// to 'b' and returns LCA of a and b. Time Complexity : O(n)` `    ``static` `int` `LCA(``int` `a, ``int` `b) ` `    ``{` `        ``// trivial case` `        ``if` `(a == b)` `            ``return` `a;`   `        ``// setting root to be first element in path` `        ``path[``1``][``0``] = path[``2``][``0``] = ``1``;`   `        ``// calculating path from root to a` `        ``flag = ``false``;` `        ``dfs(``1``, ``0``, ``1``, ``1``, a);`   `        ``// calculating path from root to b` `        ``flag = ``false``;` `        ``dfs(``1``, ``0``, ``2``, ``1``, b);`   `        ``// runs till path 1 & path 2 matches` `        ``int` `i = ``0``;` `        ``while` `(i < MAXN && path[``1``][i] == path[``2``][i])` `            ``i++;`   `        ``// returns the last matching node in the paths` `        ``return` `path[``1``][i - ``1``];` `    ``}`   `    ``static` `void` `addEdge(``int` `a, ``int` `b) ` `    ``{` `        ``tree[a].add(b);` `        ``tree[b].add(a);` `    ``}`   `    ``// Driver code` `    ``public` `static` `void` `main(String[] args) ` `    ``{` `        ``for` `(``int` `i = ``0``; i < MAXN; i++)` `            ``tree[i] = ``new` `Vector();`   `        ``// Number of nodes` `        ``addEdge(``1``, ``2``);` `        ``addEdge(``1``, ``3``);` `        ``addEdge(``2``, ``4``);` `        ``addEdge(``2``, ``5``);` `        ``addEdge(``2``, ``6``);` `        ``addEdge(``3``, ``7``);` `        ``addEdge(``3``, ``8``);`   `        ``System.out.print(``"LCA(4, 7) = "` `+ LCA(``4``, ``7``) + ``"\n"``);` `        ``System.out.print(``"LCA(4, 6) = "` `+ LCA(``4``, ``6``) + ``"\n"``);` `    ``}` `}`   `// This code is contributed by 29AjayKumar`

## Python3

 `# Python3 program to find LCA of n1 and ` `# n2 using one DFS on the Tree `   `# Maximum number of nodes is 100000 and` `# nodes are numbered from 1 to 100000` `MAXN ``=` `100001`   `tree ``=` `[``0``] ``*` `MAXN` `for` `i ``in` `range``(MAXN):` `    ``tree[i] ``=` `[]`   `# Storing root to node path` `path ``=` `[``0``] ``*` `3` `for` `i ``in` `range``(``3``):` `    ``path[i] ``=` `[``0``] ``*` `MAXN`   `flag ``=` `False`   `# Storing the path from root to node` `def` `dfs(cur: ``int``, prev: ``int``, pathNumber: ``int``,` `        ``ptr: ``int``, node: ``int``) ``-``> ``None``:` `            `  `    ``global` `tree, path, flag`   `    ``for` `i ``in` `range``(``len``(tree[cur])):` `        ``if` `(tree[cur][i] !``=` `prev ``and` `not` `flag):`   `            ``# Pushing current node into the path` `            ``path[pathNumber][ptr] ``=` `tree[cur][i]` `            `  `            ``if` `(tree[cur][i] ``=``=` `node):`   `                ``# Node found` `                ``flag ``=` `True`   `                ``# Terminating the path` `                ``path[pathNumber][ptr ``+` `1``] ``=` `-``1` `                ``return`   `            ``dfs(tree[cur][i], cur, pathNumber,` `                ``ptr ``+` `1``, node)`   `# This Function compares the path from root ` `# to 'a' & root to 'b' and returns LCA of ` `# a and b. Time Complexity : O(n)` `def` `LCA(a: ``int``, b: ``int``) ``-``> ``int``:` `    `  `    ``global` `flag` `    `  `    ``# Trivial case` `    ``if` `(a ``=``=` `b):` `        ``return` `a`   `    ``# Setting root to be first element ` `    ``# in path` `    ``path[``1``][``0``] ``=` `path[``2``][``0``] ``=` `1`   `    ``# Calculating path from root to a` `    ``flag ``=` `False` `    ``dfs(``1``, ``0``, ``1``, ``1``, a)`   `    ``# Calculating path from root to b` `    ``flag ``=` `False` `    ``dfs(``1``, ``0``, ``2``, ``1``, b)`   `    ``# Runs till path 1 & path 2 matches` `    ``i ``=` `0` `    ``while` `(path[``1``][i] ``=``=` `path[``2``][i]):` `        ``i ``+``=` `1`   `    ``# Returns the last matching ` `    ``# node in the paths` `    ``return` `path[``1``][i ``-` `1``]`   `def` `addEdge(a: ``int``, b: ``int``) ``-``> ``None``:`   `    ``tree[a].append(b)` `    ``tree[b].append(a)`   `# Driver code` `if` `__name__ ``=``=` `"__main__"``:`   `    ``n ``=` `8` `    `  `    ``# Number of nodes` `    ``addEdge(``1``, ``2``)` `    ``addEdge(``1``, ``3``)` `    ``addEdge(``2``, ``4``)` `    ``addEdge(``2``, ``5``)` `    ``addEdge(``2``, ``6``)` `    ``addEdge(``3``, ``7``)` `    ``addEdge(``3``, ``8``)`   `    ``print``(``"LCA(4, 7) = {}"``.``format``(LCA(``4``, ``7``)))` `    ``print``(``"LCA(4, 6) = {}"``.``format``(LCA(``4``, ``6``)))`   `# This code is contributed by sanjeev2552`

## C#

 `/* C# Program to find LCA of n1 and n2 using one DFS on` `the Tree */` `using` `System;` `using` `System.Collections.Generic;`   `class` `GFG ` `{`   `    ``// Maximum number of nodes is 100000 and nodes are` `    ``// numbered from 1 to 100000` `    ``static` `readonly` `int` `MAXN = 100001;`   `    ``static` `List<``int``>[] tree = ``new` `List<``int``>[MAXN];` `    ``static` `int``[,] path = ``new` `int``[3, MAXN]; ``// storing root to node path` `    ``static` `bool` `flag;`   `    ``// storing the path from root to node` `    ``static` `void` `dfs(``int` `cur, ``int` `prev, ``int` `pathNumber, ``int` `ptr, ``int` `node) ` `    ``{` `        ``for` `(``int` `i = 0; i < tree[cur].Count; i++) ` `        ``{` `            ``if` `(tree[cur][i] != prev && !flag)` `            ``{` `                ``// pushing current node into the path` `                ``path[pathNumber,ptr] = tree[cur][i];` `                ``if` `(tree[cur][i] == node) ` `                ``{` `                    ``// node found` `                    ``flag = ``true``;`   `                    ``// terminating the path` `                    ``path[pathNumber, ptr + 1] = -1;` `                    ``return``;` `                ``}` `                ``dfs(tree[cur][i], cur, pathNumber, ptr + 1, node);` `            ``}` `        ``}` `    ``}`   `    ``// This Function compares the path from root to 'a' & root` `    ``// to 'b' and returns LCA of a and b. Time Complexity : O(n)` `    ``static` `int` `LCA(``int` `a, ``int` `b) ` `    ``{` `        ``// trivial case` `        ``if` `(a == b)` `            ``return` `a;`   `        ``// setting root to be first element in path` `        ``path[1, 0] = path[2, 0] = 1;`   `        ``// calculating path from root to a` `        ``flag = ``false``;` `        ``dfs(1, 0, 1, 1, a);`   `        ``// calculating path from root to b` `        ``flag = ``false``;` `        ``dfs(1, 0, 2, 1, b);`   `        ``// runs till path 1 & path 2 matches` `        ``int` `i = 0;` `        ``while` `(i < MAXN && path[1, i] == path[2, i])` `            ``i++;`   `        ``// returns the last matching node in the paths` `        ``return` `path[1, i - 1];` `    ``}`   `    ``static` `void` `addEdge(``int` `a, ``int` `b) ` `    ``{` `        ``tree[a].Add(b);` `        ``tree[b].Add(a);` `    ``}`   `    ``// Driver code` `    ``public` `static` `void` `Main(String[] args) ` `    ``{` `        ``for` `(``int` `i = 0; i < MAXN; i++)` `            ``tree[i] = ``new` `List<``int``>();`   `        ``// Number of nodes` `        ``addEdge(1, 2);` `        ``addEdge(1, 3);` `        ``addEdge(2, 4);` `        ``addEdge(2, 5);` `        ``addEdge(2, 6);` `        ``addEdge(3, 7);` `        ``addEdge(3, 8);`   `        ``Console.Write(``"LCA(4, 7) = "` `+ LCA(4, 7) + ``"\n"``);` `        ``Console.Write(``"LCA(4, 6) = "` `+ LCA(4, 6) + ``"\n"``);` `    ``}` `}`   `// This code is contributed by Rajput-Ji`

## Javascript

 ``

Output

```LCA(4, 7) = 1
LCA(4, 6) = 2```

Sparse Matrix Approach (O(nlogn) pre-processing, O(log n) – query)

Pre-computation:

Here we store the 2^i th parent for every node, where 0 <= i < LEVEL, here “LEVEL” is a constant integer that tells the maximum number of 2^i th ancestor possible.

Therefore, we assume the worst case to see what is the value of the constant LEVEL. In our worst case every node in our tree will have at max 1 parent and 1 child or we can say it simply reduces to a linked list.

So, in this case LEVEL = ceil ( log(number of nodes) ).

We also pre-compute the height for each node using one dfs in O(n) time.

```int n             // number of nodes
int parent[MAXN][LEVEL] // all initialized to -1

parent[node][0] : contains the 2^0th(first)
parent of all the nodes pre-computed using DFS

// Sparse matrix Approach
for node -> 1 to n :
for i-> 1 to LEVEL :
if ( parent[node][i-1] != -1 ) :
parent[node][i]  =
parent[ parent[node][i-1] ][i-1]```

Now , as we see the above dynamic programming code runs two nested loop that runs over their complete range respectively.
Hence, it can be easily be inferred that its asymptotic Time Complexity is O(number of nodes * LEVEL) ~ O(n*LEVEL) ~ O(nlogn).

Return LCA(u,v):

1. First Step is to bring both the nodes at the same height. As we have already pre-computed the heights for each node. We first calculate the difference in the heights of u and v (let’s say v >=u). Now we need the node ‘v’ to jump h nodes above. This can be easily done in O(log h) time ( where h is the difference in the heights of u and v) as we have already stored the 2^i parent for each node. This process is exactly same as calculating x^y in O(log y) time. (See the code for better understanding).
2. Now both u and v nodes are at same height. Therefore now once again we will use 2^i jumping strategy to reach the first Common Parent of u and v.
```Pseudo-code:
For i->  LEVEL to 0 :
If parent[u][i] != parent[v][i] :
u = parent[u][i]
v = parent[v][i]```

Implementation of the above algorithm is given below:

## C++

 `// Sparse Matrix DP approach to find LCA of two nodes ` `#include ` `using` `namespace` `std; ` `#define MAXN 100000 ` `#define level 18 `   `vector <``int``> tree[MAXN]; ` `int` `depth[MAXN]; ` `int` `parent[MAXN][level]; `   `// pre-compute the depth for each node and their ` `// first parent(2^0th parent) ` `// time complexity : O(n) ` `void` `dfs(``int` `cur, ``int` `prev) ` `{ ` `    ``depth[cur] = depth[prev] + 1; ` `    ``parent[cur][0] = prev; ` `    ``for` `(``int` `i=0; i>i)&1) ` `            ``v = parent[v][i]; `   `    ``// now depth[u] == depth[v] ` `    ``if` `(u == v) ` `        ``return` `u; `   `    ``// Step 2 of the pseudocode ` `    ``for` `(``int` `i=level-1; i>=0; i--) ` `        ``if` `(parent[u][i] != parent[v][i]) ` `        ``{ ` `            ``u = parent[u][i]; ` `            ``v = parent[v][i]; ` `        ``} `   `    ``return` `parent[u][0]; ` `} `   `void` `addEdge(``int` `u,``int` `v) ` `{ ` `    ``tree[u].push_back(v); ` `    ``tree[v].push_back(u); ` `} `   `// driver function ` `int` `main() ` `{ ` `    ``memset``(parent,-1,``sizeof``(parent)); ` `    ``int` `n = 8; ` `    ``addEdge(1,2); ` `    ``addEdge(1,3); ` `    ``addEdge(2,4); ` `    ``addEdge(2,5); ` `    ``addEdge(2,6); ` `    ``addEdge(3,7); ` `    ``addEdge(3,8); ` `    ``depth[0] = 0; `   `    ``// running dfs and precalculating depth ` `    ``// of each node. ` `    ``dfs(1,0); `   `    ``// Precomputing the 2^i th ancestor for every node ` `    ``precomputeSparseMatrix(n); `   `    ``// calling the LCA function ` `    ``cout << ``"LCA(4, 7) = "` `<< lca(4,7) << endl; ` `    ``cout << ``"LCA(4, 6) = "` `<< lca(4,6) << endl; ` `    ``return` `0; ` `} `

## Java

 `// Sparse Matrix DP approach to find LCA of two nodes` `import` `java.util.*;`   `class` `GFG ` `{` `    ``static` `final` `int` `MAXN = ``100000``;` `    ``static` `final` `int` `level = ``18``;` `  `  `      ``@SuppressWarnings``(``"unchecked"``)` `    ``static` `Vector[] tree = ``new` `Vector[MAXN];` `    ``static` `int``[] depth = ``new` `int``[MAXN];` `    ``static` `int``[][] parent = ``new` `int``[MAXN][level];`   `    ``// pre-compute the depth for each node and their` `    ``// first parent(2^0th parent)` `    ``// time complexity : O(n)` `    ``static` `void` `dfs(``int` `cur, ``int` `prev)` `    ``{` `        ``depth[cur] = depth[prev] + ``1``;` `        ``parent[cur][``0``] = prev;` `        ``for` `(``int` `i = ``0``; i < tree[cur].size(); i++) ` `        ``{` `            ``if` `(tree[cur].get(i) != prev)` `                ``dfs(tree[cur].get(i), cur);` `        ``}` `    ``}`   `    ``// Dynamic Programming Sparse Matrix Approach` `    ``// populating 2^i parent for each node` `    ``// Time complexity : O(nlogn)` `    ``static` `void` `precomputeSparseMatrix(``int` `n) ` `    ``{` `        ``for` `(``int` `i = ``1``; i < level; i++) ` `        ``{` `            ``for` `(``int` `node = ``1``; node <= n; node++)` `            ``{` `                ``if` `(parent[node][i - ``1``] != -``1``)` `                    ``parent[node][i] = parent[parent[node][i - ``1``]][i - ``1``];` `            ``}` `        ``}` `    ``}`   `    ``// Returning the LCA of u and v` `    ``// Time complexity : O(log n)` `    ``static` `int` `lca(``int` `u, ``int` `v)` `    ``{` `        ``if` `(depth[v] < depth[u])` `        ``{` `            ``u = u + v;` `            ``v = u - v;` `            ``u = u - v;` `        ``}`   `        ``int` `diff = depth[v] - depth[u];`   `        ``// Step 1 of the pseudocode` `        ``for` `(``int` `i = ``0``; i < level; i++)` `            ``if` `(((diff >> i) & ``1``) == ``1``)` `                ``v = parent[v][i];`   `        ``// now depth[u] == depth[v]` `        ``if` `(u == v)` `            ``return` `u;`   `        ``// Step 2 of the pseudocode` `        ``for` `(``int` `i = level - ``1``; i >= ``0``; i--)` `            ``if` `(parent[u][i] != parent[v][i]) ` `            ``{` `                ``u = parent[u][i];` `                ``v = parent[v][i];` `            ``}`   `        ``return` `parent[u][``0``];` `    ``}`   `    ``static` `void` `addEdge(``int` `u, ``int` `v)` `    ``{` `        ``tree[u].add(v);` `        ``tree[v].add(u);` `    ``}`   `    ``static` `void` `memset(``int` `value) ` `    ``{` `        ``for` `(``int` `i = ``0``; i < MAXN; i++)` `        ``{` `            ``for` `(``int` `j = ``0``; j < level; j++)` `            ``{` `                ``parent[i][j] = -``1``;` `            ``}` `        ``}` `    ``}`   `    ``// driver function` `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``memset(-``1``);` `        ``for` `(``int` `i = ``0``; i < MAXN; i++)` `            ``tree[i] = ``new` `Vector();` `        ``int` `n = ``8``;` `        ``addEdge(``1``, ``2``);` `        ``addEdge(``1``, ``3``);` `        ``addEdge(``2``, ``4``);` `        ``addEdge(``2``, ``5``);` `        ``addEdge(``2``, ``6``);` `        ``addEdge(``3``, ``7``);` `        ``addEdge(``3``, ``8``);` `        ``depth[``0``] = ``0``;`   `        ``// running dfs and precalculating depth` `        ``// of each node.` `        ``dfs(``1``, ``0``);`   `        ``// Precomputing the 2^i th ancestor for every node` `        ``precomputeSparseMatrix(n);`   `        ``// calling the LCA function` `        ``System.out.print(``"LCA(4, 7) = "` `+ lca(``4``, ``7``) + ``"\n"``);` `        ``System.out.print(``"LCA(4, 6) = "` `+ lca(``4``, ``6``) + ``"\n"``);` `    ``}` `}`   `// This code is contributed by 29AjayKumar`

## Python3

 `# Sparse Matrix DP approach to find LCA of two nodes` `MAXN ``=` `100000` `level ``=` `18` `tree ``=` `[[] ``for` `_ ``in` `range``(MAXN)]` `depth ``=` `[``0` `for` `_ ``in` `range``(MAXN)]` `parent ``=` `[[``-``1` `for` `_ ``in` `range``(level)] ``for` `_ ``in` `range``(MAXN)]`   `# pre-compute the depth for each node and their` `# first parent(2^0th parent)` `# time complexity : O(n)`     `def` `dfs(cur, prev):` `    ``depth[cur] ``=` `depth[prev] ``+` `1` `    ``parent[cur][``0``] ``=` `prev` `    ``for` `i ``in` `range``(``len``(tree[cur])):` `        ``if` `tree[cur][i] !``=` `prev:` `            ``dfs(tree[cur][i], cur)`   `# Dynamic Programming Sparse Matrix Approach` `# populating 2^i parent for each node` `# Time complexity : O(nlogn)`     `def` `precompute_sparse_matrix(n):` `    ``for` `i ``in` `range``(``1``, level):` `        ``for` `node ``in` `range``(``1``, n``+``1``):` `            ``if` `parent[node][i``-``1``] !``=` `-``1``:` `                ``parent[node][i] ``=` `parent[parent[node][i``-``1``]][i``-``1``]`   `# Returning the LCA of u and v` `# Time complexity : O(log n)`     `def` `lca(u, v):` `    ``if` `depth[v] < depth[u]:` `        ``u, v ``=` `v, u` `    ``diff ``=` `depth[v] ``-` `depth[u]` `    ``# Step 1 of the pseudocode` `    ``for` `i ``in` `range``(level):` `        ``if` `(diff >> i) & ``1` `=``=` `1``:` `            ``v ``=` `parent[v][i]` `    ``# now depth[u] == depth[v]` `    ``if` `u ``=``=` `v:` `        ``return` `u` `    ``# Step 2 of the pseudocode` `    ``for` `i ``in` `range``(level``-``1``, ``-``1``, ``-``1``):` `        ``if` `parent[u][i] !``=` `parent[v][i]:` `            ``u ``=` `parent[u][i]` `            ``v ``=` `parent[v][i]` `    ``return` `parent[u][``0``]`     `def` `add_edge(u, v):` `    ``tree[u].append(v)` `    ``tree[v].append(u)`     `def` `memset(value):` `    ``for` `i ``in` `range``(MAXN):` `        ``for` `j ``in` `range``(level):` `            ``parent[i][j] ``=` `-``1`     `# Driver function`   `n ``=` `8` `add_edge(``1``, ``2``)` `add_edge(``1``, ``3``)` `add_edge(``2``, ``4``)` `add_edge(``2``, ``5``)` `add_edge(``2``, ``6``)` `add_edge(``3``, ``7``)` `add_edge(``3``, ``8``)` `depth[``0``] ``=` `0` `# running dfs and precalculating depth` `# of each node.` `dfs(``1``, ``0``)` `# Precomputing the 2^i th ancestor for every node` `precompute_sparse_matrix(n)` `# calling the LCA function` `print``(``"LCA(4, 7) = "``, lca(``4``, ``7``))` `print``(``"LCA(4, 6) = "``, lca(``4``, ``6``))`

## C#

 `// Sparse Matrix DP approach to find LCA of two nodes` `using` `System;` `using` `System.Collections.Generic;`   `class` `GFG ` `{` `    ``static` `readonly` `int` `MAXN = 100000;` `    ``static` `readonly` `int` `level = 18;`   `    ``static` `List<``int``>[] tree = ``new` `List<``int``>[MAXN];` `    ``static` `int``[] depth = ``new` `int``[MAXN];` `    ``static` `int``[,] parent = ``new` `int``[MAXN, level];`   `    ``// pre-compute the depth for each node and their` `    ``// first parent(2^0th parent)` `    ``// time complexity : O(n)` `    ``static` `void` `dfs(``int` `cur, ``int` `prev)` `    ``{` `        ``depth[cur] = depth[prev] + 1;` `        ``parent[cur,0] = prev;` `        ``for` `(``int` `i = 0; i < tree[cur].Count; i++) ` `        ``{` `            ``if` `(tree[cur][i] != prev)` `                ``dfs(tree[cur][i], cur);` `        ``}` `    ``}`   `    ``// Dynamic Programming Sparse Matrix Approach` `    ``// populating 2^i parent for each node` `    ``// Time complexity : O(nlogn)` `    ``static` `void` `precomputeSparseMatrix(``int` `n) ` `    ``{` `        ``for` `(``int` `i = 1; i < level; i++) ` `        ``{` `            ``for` `(``int` `node = 1; node <= n; node++)` `            ``{` `                ``if` `(parent[node, i - 1] != -1)` `                    ``parent[node, i] = parent[parent[node, i - 1], i - 1];` `            ``}` `        ``}` `    ``}`   `    ``// Returning the LCA of u and v` `    ``// Time complexity : O(log n)` `    ``static` `int` `lca(``int` `u, ``int` `v)` `    ``{` `        ``if` `(depth[v] < depth[u])` `        ``{` `            ``u = u + v;` `            ``v = u - v;` `            ``u = u - v;` `        ``}`   `        ``int` `diff = depth[v] - depth[u];`   `        ``// Step 1 of the pseudocode` `        ``for` `(``int` `i = 0; i < level; i++)` `            ``if` `(((diff >> i) & 1) == 1)` `                ``v = parent[v, i];`   `        ``// now depth[u] == depth[v]` `        ``if` `(u == v)` `            ``return` `u;`   `        ``// Step 2 of the pseudocode` `        ``for` `(``int` `i = level - 1; i >= 0; i--)` `            ``if` `(parent[u, i] != parent[v, i]) ` `            ``{` `                ``u = parent[u, i];` `                ``v = parent[v, i];` `            ``}`   `        ``return` `parent[u, 0];` `    ``}`   `    ``static` `void` `addEdge(``int` `u, ``int` `v)` `    ``{` `        ``tree[u].Add(v);` `        ``tree[v].Add(u);` `    ``}`   `    ``static` `void` `memset(``int` `value) ` `    ``{` `        ``for` `(``int` `i = 0; i < MAXN; i++)` `        ``{` `            ``for` `(``int` `j = 0; j < level; j++)` `            ``{` `                ``parent[i, j] = -1;` `            ``}` `        ``}` `    ``}`   `    ``// Driver function` `    ``public` `static` `void` `Main(String[] args)` `    ``{` `        ``memset(-1);` `        ``for` `(``int` `i = 0; i < MAXN; i++)` `            ``tree[i] = ``new` `List<``int``>();` `        ``int` `n = 8;` `        ``addEdge(1, 2);` `        ``addEdge(1, 3);` `        ``addEdge(2, 4);` `        ``addEdge(2, 5);` `        ``addEdge(2, 6);` `        ``addEdge(3, 7);` `        ``addEdge(3, 8);` `        ``depth[0] = 0;`   `        ``// running dfs and precalculating depth` `        ``// of each node.` `        ``dfs(1, 0);`   `        ``// Precomputing the 2^i th ancestor for every node` `        ``precomputeSparseMatrix(n);`   `        ``// calling the LCA function` `        ``Console.Write(``"LCA(4, 7) = "` `+ lca(4, 7) + ``"\n"``);` `        ``Console.Write(``"LCA(4, 6) = "` `+ lca(4, 6) + ``"\n"``);` `    ``}` `}`   `// This code is contributed by PrinciRaj1992`

## Javascript

 ``

Output

```LCA(4, 7) = 1
LCA(4, 6) = 2```

Time Complexity:

The time complexity for answering a single LCA query will be O(logn) but the overall time complexity is dominated by precalculation of the 2^i th ( 0<=i<=level ) ancestors for each node. Hence, the overall asymptotic Time Complexity will be O(n*logn) and Space Complexity will be O(nlogn), for storing the data about the ancestors of each node.

This article is contributed by Nitish Kumar. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

My Personal Notes arrow_drop_up