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.
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more, please refer Complete Interview Preparation Course.
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] = i-th node’s 2^(j)th ancestor in the path
memo[i][j] = memo[i] (first parent (2^0) of each node is given)
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))
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:
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)