# 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 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[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][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:

`// Java implementation of the approach ` `import` `java.util.*; ` `public` `class` `GFG { ` ` ` ` ` `// ArrayList to store tree ` ` ` `static` `ArrayList<Integer> 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` `)); ` ` ` `} ` `} ` |

*chevron_right*

*filter_none*

**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).

## Recommended Posts:

- Complexity of different operations in Binary tree, Binary Search Tree and AVL tree
- Minimum swap required to convert binary tree to binary search tree
- Check whether a binary tree is a full binary tree or not | Iterative Approach
- Convert a Binary Tree to Threaded binary tree | Set 1 (Using Queue)
- Convert a Binary Tree to Threaded binary tree | Set 2 (Efficient)
- Binary Tree to Binary Search Tree Conversion
- Binary Tree to Binary Search Tree Conversion using STL set
- Check whether a given binary tree is skewed binary tree or not?
- Check if a binary tree is subtree of another binary tree | Set 2
- Check if a binary tree is subtree of another binary tree | Set 1
- Check whether a binary tree is a full binary tree or not
- Print Binary Tree levels in sorted order | Set 3 (Tree given as array)
- Given level order traversal of a Binary Tree, check if the Tree is a Min-Heap
- Convert an arbitrary Binary Tree to a tree that holds Children Sum Property
- Convert a given Binary tree to a tree that holds Logical AND property

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.