Lowest Common Ancestor of a Binary Tree Part II
July 21, 2011 in binary tree
Given a binary tree, find the lowest common ancestor of two given nodes in the tree. Each node contains a parent pointer which links to its parent.
Note:
This is Part II of Lowest Common Ancestor of a Binary Tree. If you need to find the lowest common ancestor without parent pointers, please read Lowest Common Ancestor of a Binary Tree Part I.
_______3______ / \ ___5__ ___1__ / \ / \ 6 _2 0 8 / \ 7 4
If you are not so sure about the definition of lowest common ancestor (LCA), please refer to my previous post: Lowest Common Ancestor of a Binary Search Tree (BST) or the definition of LCA here. Using the tree above as an example, the LCA of nodes 5 and 1 is 3. Please note that LCA for nodes 5 and 4 is 5.
In my last post: Lowest Common Ancestor of a Binary Tree Part I, we have devised a recursive solution which finds the LCA in O(n) time. If each node has a pointer that link to its parent, could we devise a better solution?
Hint:
No recursion is needed. There is an easy solution which uses extra space. Could you eliminate the need of extra space?
An easy solution:
As we trace the two paths from both nodes up to the root, eventually it will merge into one single path. The LCA is the exact first intersection node where both paths merged into a single path. An easy solution is to use a hash table which records visited nodes as we trace both paths up to the root. Once we reached the first node which is already marked as visited, we immediately return that node as the LCA.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Node *LCA(Node *root, Node *p, Node *q) { hash_set<Node *> visited; while (p || q) { if (p) { if (!visited.insert(p).second) return p; // insert p failed (p exists in the table) p = p->parent; } if (q) { if (!visited.insert(q).second) return q; // insert q failed (q exists in the table) q = q->parent; } } return NULL; } |
The run time complexity of this approach is O(h), where h is the tree’s height. The space complexity is also O(h), since it can mark at most 2h nodes.
The best solution:
A little creativity is needed here. Since we have the parent pointer, we could easily get the distance (height) of both nodes from the root. Once we knew both heights, we could subtract from one another and get the height’s difference (dh). If you observe carefully from the previous solution, the node which is closer to the root is always dh steps ahead of the deeper node. We could eliminate the need of marking visited nodes altogether. Why?
The reason is simple, if we advance the deeper node dh steps above, both nodes would be at the same depth. Then, we advance both nodes one level at a time. They would then eventually intersect at one node, which is the LCA of both nodes. If not, one of the node would eventually reach NULL (root’s parent), which we conclude that both nodes are not in the same tree. However, that part of code shouldn’t be reached, since the problem statement assumed that both nodes are in the same tree.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | int getHeight(Node *p) { int height = 0; while (p) { height++; p = p->parent; } return height; } // As root->parent is NULL, we don't need to pass root in. Node *LCA(Node *p, Node *q) { int h1 = getHeight(p); int h2 = getHeight(q); // swap both nodes in case p is deeper than q. if (h1 > h2) { swap(h1, h2); swap(p, q); } // invariant: h1 <= h2. int dh = h2 - h1; for (int h = 0; h < dh; h++) q = q->parent; while (p && q) { if (p == q) return p; p = p->parent; q = q->parent; } return NULL; // p and q are not in the same tree } |
Further Thoughts:
Isn’t the solution above neat? It requires some creative thought and is quite subtle.
A variation of this problem which seemed to be more popular is:
Given two singly linked lists and they both intersect at one point (ie, forming a Y shaped list). Find where the two linked lists merge.
I am sure you know how to answer this question now ![]()

Pankaj said on July 22, 2011
Please try to remove add if possible.
Instead add a paypal option so that those who get benefit from your blog can support this hard work of yours
maxq said on July 23, 2011
There seems to be a bug in your code?
Please see below.
Node *LCA(Node *root, Node *p, Node *q) {
hash_set visited;
while (p || q) {
if (p) {
if (!visited.insert(p).second)
return p; // insert p failed (p exists in the table)
p = p->parent;
}
if (q) {
if (!visited.insert(p).second) parent;
}
}
return NULL;
1337c0d3r said on July 23, 2011
Are you saying that on line 10:
(!visited.insert(p).second)
should be:
(!visited.insert(q).second)
If that is, this is a mistake and thanks for pointing that out. I will correct the post later.
Alex said on February 20, 2012
What is “second” in (!visited.insert(q).second) ?
I know in Java, for “visited.add(q)”, if q exists, it will return false. But here, what is the mean of “second” ?
1337c0d3r said on February 20, 2012
The insert() function returns a pair.
The insert member function returns a pair whose bool component returns true if an insertion was make and false if the hash_set already contained an element whose key had an equivalent value in the ordering
http://msdn.microsoft.com/en-us/library/2t5cf4t8%28v=vs.80%29.aspx
Chetan Sharma said on July 25, 2011
Various solution to the Y shaped linked list problem exists, one of them being:
Start traversing first list setting the next pointer to NULL in the process. Now start traversing the second list until the next pointer of a node is not NULL. At this point the current node is the intersecting node. Though this solution requires modification to the list but is more efficient as you need to traverse the list only once
fangstar said on November 8, 2011
For the Y shaped linked list problem, instead of difference in height we need to calculate the difference in length between the linked lists right?
Then do the similar advancement on the longer length, and then iterate for a match?
TIY
Eugene Kirpichov said on March 28, 2012
The solution is indeed neat, but I would not call it “best” in all situations. It requires at least traversing both nodes to the root, whereas the “easy” solution may stop much earlier than that.
景泰蓝 said on April 5, 2012
Node *LCA(Node *root, Node *p, Node *q){
Node * q_path[MAX] , p_path[MAX];
int qi=0, pi=0;
while(q) { q_path[qi++]=q; q=q->parent ;}
while(p) { p_path[pi++]}=p; p=p->parent; }
while(qi>=0 && pi>=0){ if(q_path[--qi] != p_path[--pi]) return p_path[qi] ; }
return NULL;
}
Raja said on June 2, 2012
The LCA of 6 and 2 in the example should be 5 or 3 ? Since its lowest common ancestor – Shouldnt it be 3 ?
But the code given would give us 5 as the answer. Please clarify ?
Thanks,
Raja.
Ganesh R said on July 27, 2012
You are using parent.. But the actual structure of a Binary tree should be
struct tree
{
struct tree *lchild;
struct tree *rchild;
int element;
};
If additional varialbles or terms added, can it called a Binary tree???
George said on August 12, 2012
Yes, a binary tree doesn’t stop being a binary tree if you add a pointer to the parent node. The solution provided is indeed very creative
Daniel said on August 19, 2012
There is a better solution…
The suggested solution is o(depth of tree), there is a solution in o(distance of two nodes).
1.Note: Once you find a common ancestor, you can find the differences between the two nodes heights, and find the lowest common ancestor.
2. In order to find a common ancesstor in o(distance) you can walk up in the tree alternately with each pointer in the following way:
a. first you will go with the first pointer 1 step.
b. with the second pointer 2 steps.
c. with the first pointer 4 steps.. etc
where in each step you compare the pointers, and you stop once they are equal.
On the iteration where the number of steps is >= distance of the two nodes, you will find some common ancestor o(distance).
Tong Liu said on December 30, 2012
it is like another question finding intersection of two linked list
Raj said on January 21, 2013
COuld you please explain it.I did not understand How do we go back like p=p->parents.
Partha Pratim Sirker said on January 22, 2013
Although it is similar to a Y shaped linkedlist problem, the solution would involve find out the path of the nodes separately which is of O(n) operation. So in total we will do two iteration of O(n) and then O(log n) to find out the Y junction. (Assuming there is no parent pointer). I found this solution better where there is only one iteration and it is of O(n) complexity. It is done with a single post-order traversal. http://www.dsalgo.com/LowestCommonAncestor.php
pavi said on February 22, 2013
The solution given in the link you provided and what you are talking about is similar (or exactly same) to the one given in the part 1 of this Article.
Here’s the link:
http://leetcode.com/2011/07/lowest-common-ancestor-of-a-binary-tree-part-i.html
Prateek Caire said on February 24, 2013
How about this one.Move one of the nodes up and delink the parent by putting null to parent pointer.Move second node up till we do not find delinked parent. That node is LCA. Solution, however, alters tree structure
DaShan said on March 17, 2013
I don’t think computing the nodes’ heights is necessary:
-Assuming we store the “root-to-node” path in a stack
-Then going down to child node is represented by a stack “push”, and a backtrack is achieved by a stack pop
-(1) After finding the 1st node, we have a stack that stores the path from the root to the 1st node
-(2) Then we continue the traversal, by “pop”, “push”, “push”, …, until reaching the 2nd node
-between (1) and (2), a prefix of the stack, namely from the root to the LCA, will not change
-therefore, we can use a “watermark pointer” to maintain “the lowest element of the stack content at (1) that survives till (2) is done”.
-Once (2) is done, the above “watermark pointer” points to the LCA.
Siyong said on March 21, 2013
That would require extra memory.