Lowest Common Ancestor in a Binary Search Tree.
Given the values of two nodes in a *binary search tree*, write a c program to find the lowest common ancestor. You may assume that both values already exist in the tree.
The function prototype is as follows:
int FindLowestCommonAncestor(node* root, int value1, int value)

I/P : 4 and 14
O/P : 8
(Here the common ancestors of 4 and 14, are {8,20}.
Of {8,20}, the lowest one is 8).
Here is the solution
Algorithm:
The main idea of the solution is — While traversing Binary Search Tree from top to bottom, the first node n we encounter with value between n1 and n2, i.e., n1 < n < n2 is the Lowest or Least Common Ancestor(LCA) of n1 and n2 (where n1 < n2). So just traverse the BST in pre-order, if you find a node with value in between n1 and n2 then n is the LCA, if it's value is greater than both n1 and n2 then our LCA lies on left side of the node, if it's value is smaller than both n1 and n2 then LCA lies on right side.
Implementation:
#include <stdio.h>
#include <stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node* left;
struct node* right;
};
struct node* newNode(int );
/* Function to find least comman ancestor of n1 and n2 */
int leastCommanAncestor(struct node* root, int n1, int n2)
{
/* If we have reached a leaf node then LCA doesn't exist
If root->data is equal to any of the inputs then input is
not valid. For example 20, 22 in the given figure */
if(root == NULL || root->data == n1 || root->data == n2)
return -1;
/* If any of the input nodes is child of the current node
we have reached the LCA. For example, in the above figure
if we want to calculate LCA of 12 and 14, recursion should
terminate when we reach 8*/
if((root->right != NULL) &&
(root->right->data == n1 || root->right->data == n2))
return root->data;
if((root->left != NULL) &&
(root->left->data == n1 || root->left->data == n2))
return root->data;
if(root->data > n1 && root->data < n2)
return root->data;
if(root->data > n1 && root->data > n2)
return leastCommanAncestor(root->left, n1, n2);
if(root->data < n1 && root->data < n2)
return leastCommanAncestor(root->right, n1, n2);
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
/* Driver program to test mirror() */
int main()
{
struct node *root = newNode(2);
root->left = newNode(1);
root->right = newNode(4);
root->right->left = newNode(3);
root->right->right = newNode(5);
/* Constructed binary search tree is
2
/ \
1 4
/ \
3 5
*/
printf("\n The Least Common Ancestor is \n");
printf("%d", leastCommanAncestor(root, 3, 5));
getchar();
return 0;
}
Note that above function assumes that n1 is smaller than n2.
Time complexity: Time complexity is O(Logn) for a balanced BST and O(n) for a skewed BST.
The question was asked by Varun Bhatia
You may also like following posts
I think this is absolute solution because its taken from Stanford University notes http://cslibrary.stanford.edu/110/
Can someone provide a Java version for this algorithm?
This code take care of all the condition ... Easiest solution : int checkexist(binary *start,int n) { if(start == NULL) return 0; if(start->data == n) return 1; else if(start->data > n) return checkexist(start->left ,n); else return checkexist(start->right ,n); } void findcommonanc(binary *start,int n1 ,int n2) { binary *commonnoe = start ; if(!checkexist(start,n1) && !checkexist(start,n2)){ printf("data not exist"); return ; } while(start) { if(start->data >= n1 && start->data >=n2) { start =start->left ; commonnoe = start ; if(start->data == n1 || start->data ==n2) break; } else if(start->data < n1 && start->data <n2) { start =start->right ; } else break ; } printf("Common parent :%d",commonnoe->data); }The posted solution seems to be too long and unnecessary complicated.
Here is my version
// assuming both i and j and in the tree int FindLCA(Node* root, int i, int j) { while (root) { if (root->value > i && root->value>j) root = root ->pLeft; else if (root->value <i && root ->value<j) root = root ->pLeft; else return root->value; } throw std::runtime_error("Impossible to reach to this statement"); }sorry for copy-paste error
// assuming both i and j and in the tree
int FindLCA(Node* root, int i, int j)
{
while (root)
{
if (root->value > i && root->value>j)
root = root ->pLeft;
else if (root->value valuepRight;
else
return root->value;
}
throw std::runtime_error("Impossible to reach to this statement");
}
@hongping lin: The extra conditions given in solution are important. For example, your solution doesn't seem to work for LCA of 12 and 14 in the given diagram. LCA of 12 and 14 is 8. Let me know your thoughts.
How about this slight modification to the above program?
// assuming both i and j and in the tree int FindLCA(Node* root, int i, int j) { while (root) { if (root->value > i && root->value>j) root = root ->pLeft; else return root->value; } throw std::runtime_error("Impossible to reach to this statement"); }@hongping lin & @kartik- Doing slight modification to code should do the magic. Please have your say on below code. // assuming both i and j and in the tree int FindLCA(Node* root, int i, int j) { int m,n; while (root) { if (root->value > i && root->value>j) { m=root->pLeft->value; if(m==i && m==j) return root->value; else root = root ->pLeft; } else if (root->value <i && root ->value<j) { n=root->pRight->value; if(n==i && n==j) return root->value; else root = root ->pRight; } else return root->value; } throw std::runtime_error("Impossible to reach to this statement"); }Sorry By mistake i have changed || to && in code . Please find correct code below: @hongping lin & @kartik- Doing slight modification to code should do the magic. Please have your say on below code. // assuming both i and j and in the tree int FindLCA(Node* root, int i, int j) { int m,n; while (root) { if (root->value > i && root->value>j) { m=root->pLeft->value; if(m==i || m==j) return root->value; else root = root ->pLeft; } else if (root->value <i && root ->value<j) { n=root->pRight->value; if(n==i || n==j) return root->value; else root = root ->pRight; } else return root->value; } throw std::runtime_error("Impossible to reach to this statement"); }Hi,
The logic works well but only if the values exist in a btree.
Actually, in the above logic we are finding the node which finds the node from where the path to the values MAY diverge.
However, its not sure that the values will exist in the tree.
This can be soved simply by:
- get the node ptr using above algorithm
- using this node, check if both the values are in the tree whose rot is calculated above.
time complexity for the given algo should be O(log n),only in worst case when the tree is skewed it is O(n).
http://anandtechblog.blogspot.com/2010/06/least-common-ancestor.html
well...checkout this code...
int LCA(node* root,int val1,int val2) { if(!root) return 0; node* curr = root; node* par = root; while(curr) { if(curr->data < val1 && curr->data < val2) { par = curr; curr = curr->right; } else if(curr->data>val1 && curr->data>val2) { par = curr; curr = curr->left; } else{ if(val1==curr->data || val2== curr->data) curr = par; cout<<"\nLowest Common Ancestor of "<<val1<<" and "<<val2<<" is "<<curr->data; break; } } }Good one. this will be the non-recursive solution.
I think one case is missing in if..else..
if(curr->data > val1 && curr->data < val2) { cout<<curr->data; break; }yeah...thanx rightly pointed...i guess the complete code will be as follows...
int LCA(node* root,int val1,int val2) { if(!root) return 0; node* curr = root; node* par = root; while(curr) { if(curr->data < val1 && curr->data < val2) { par = curr; curr = curr->right; } else if(curr->data>val1 && curr->data>val2) { par = curr; curr = curr->left; } else if(val1==curr->data || val2== curr->data){ curr = par; cout<<"\nLowest Common Ancestor of "<<val1<<" and "<<val2<<" is "<<curr->data; break; } else if(curr->data > val1 && curr->data < val2) { cout<<curr->data; break; } } }You can ommit the if condition in the last else if statement (its redundant). Change it to:
else
{
cout<data; // or return curr->data
break;
}
Also "node* par" is not required.
That last else was reqd coz wat will happen if the root node is the lca...the left child is smaller and right chid is greater than the root! it was pointed out by someone earlier. and ya node * par is redundant...i was tracing the parent in my previous codesn forgot to remove it here... how about this one.. int LCA(node* root,int val1,int val2) { if(!root) return 0; node* curr = root; while(curr) { if(curr->data < val1 && curr->data < val2) { curr = curr->right; } else if(curr->data>val1 && curr->data>val2) { curr = curr->left; } else{ cout<<"\nLowest Common Ancestor of "<<val1<<" and "<<val2<<" is "<<curr->data; break; } } }These are the states which val1, val2 and curr->data can take (please correct me if i am worng):
1. Both Val1 and Val2 are greater than curr->data
2. Both Val1 and Val2 are less than curr->data
3. Either Val1 or Val2 is equal to curr->data
4. curr->data is between Val1 and Val2
The first 3 cases are taken care by the first three "if else" blocks.
the 4th one can simply be taken care by an else block.
@Rajesh : yeah u r right and the cases 3 and 4 are the cases when the current node is the LCA...cases 1 and 2 are taken care of...cases 3 and 4 can be handled by only 1 else statement where we just print the current node which is the LCA(the first node encountered which is greater than curr->left->data and less than curr->right->data is the required LCA isnt it?)
Great, Your solution is perfect.
^_^
#include <stdio.h> #include <stdlib.h> typedef struct node{ int d; struct node* l; struct node* r; }tree; int lca(tree* r,int a,int b) { if(r==NULL) return -1; /* If the input are not to be considered as ancestors, then: */ if(r->d==a||r->d==b) return -1; else if(r->d>b) lca(r->l,a,b); else if(r->d<a) lca(r->r,a,b); else return r->d; } tree* new(int n) { tree* t=malloc(sizeof(tree)); t->d=n; t->l=NULL; t->r=NULL; } main() { tree* r=new(20); r->l=new(8); r->r=new(22); r->l->l=new(4); r->l->r=new(12); r->l->r->l=new(10); r->l->r->r=new(14); printf("%d\n",lca(r,10,20)); return 0; }It is the Code to find LCA of two NOde in Binary Tree not In Binary Search Tree .Please Read Carefully
mynode *closestAncestor(mynode* root, mynode* p, mynode* q) { mynode *l, *r, *tmp; if(root == NULL) { return(NULL); } if(root->left==p || root->right==p || root->left==q || root->right==q) { return(root); } else { l = closestAncestor(root->left, p, q); r = closestAncestor(root->right, p, q); if(l!=NULL && r!=NULL) { return(root); } else { tmp = (l!=NULL) ? l : r; return(tmp) } } }Please Let Me know anything missing or wrong with this code
if (root->left && root->left->data == p ||
root->left && root->left->data == q ||
root->right && root->right->data == p ||
root->right && root->right->data == q)
I think it will be more better & clear , i hope i have covered all the cases in this..still if missing let me know
node* lca_BT(root,p,q)
{
if(root==null || root==p || root==q)
return null;
Case 1.
//when both p,q exist in different side
if(root->left==p||root->left==q && root->right==p || root->right==q)
return root;//True
}
case 2,3 covered here e.g. when p,q either exist on left or right & we also know if LCA exist then then its a subtree not more then height 2..isn't it..??
As there can be more common ancestor of two node but we wants LCA that what i use grandparent,parent,child all in single if condition to make sure we are getting LCS while covering all the cases as well ??
//before it we can check left or right subtree exits or /not.its not the problem..its upto programming
if(root->left==p && root->left->left==q || root->right==q && root->right->right==q)
return root;
//else or if check on both left as well right node fro each node
if(root->left==p || root->left==q)
{
lca_BT(root->left,p,q);
lca_BT(root->right,p,q);
}
//now check in right side for this node
if(root->right==p || root->right==q)
{
lca_BT(root->left,p,q);
lca_BT(root->right,p,q);
}
//else call recursively for left & right subtree as well
return (lca_BT(root->left,p,q) || lca_BT(root->right,p,q));
}
As you can see its not optimized & might contains condition which arr checking same test cases more then one so ..it will great if someone can find out that problem or anything wrong with algo or test case failure ..It will pleasure for me if this algo will work for general Binary Tree ??
how abt :
i/p 10 and 14.....ur algo gives 12 as the ans but the ans should be 8
Answer should be 12 only. Check the definition of LCA @ http://en.wikipedia.org/wiki/Lowest_common_ancestor
If you add 2 and 9 now to the tree, and then try and find their common ancestor the ans returned would be 8 (the condition n1 < n < n2 will be true), whereas it should be 4
Dumb , Dont u know how to add elements to a BST . The guy is absolutely right in his approach . necase lemmi tel u 9 will be added to left of 10 , not below 4 dumbhead .
Oops I was considering a different tree...(which was not even a BST).. Sorry for the oversight.
But in any case I don't think so you should be writing such defamatory comments. Maybe someone is new to DS and trees.!!
The program is fine . How about LCA of a tree that is not binary.
i mean 2 nodes in a tree (with any no of children at any node) would still have an LCA . What would be the logic (only algorithm) to find that?
can some one provide bioinformatics source code for protein classification
This won't work if one node is present and another is not. If you search for 10,445 , it will return 20. But 445 is not in the tree at all.
Please read the question properly. It clearly states "You may assume that both values already exist in the tree"
Solution will work if n1 n2
because:
if(root->data > n1 && root->data > n2)
return leastCommanAncestor(root->left, n1, n2);
works well if n1 < n2...
/** * Find the first common ancestor of two given nodes in a binay search tree. * * @param args * @author Pramod Chandoria */ public static Node lowestCommonParent(Node parent, Node node, int a, int b) { if (node == null) { return null; } if (a == node.data || b == node.data) { return parent; } else if (a node.data) { return node; } else if (a < node.data){ return lowestCommonParent(node, node.left,a, b); } else { return lowestCommonParent(node, node.right,a, b); } }How about finding the LCA for a binary tree (not BST).
Thanks
Finding LCA for a binary tree is the same problem as finding intersection of 2 joined linked lists. Find paths to the two nodes (as linked lists) and then use the algo for finding intersection of the two
http://geeksforgeeks.org/forum/topic/lca-of-two-nodes-in-a-binary-tree
Hi Guys...
Real good work. Do we have a straight forward algo for finding the LCA of a binary tree(not BST) ? I searched a bit and only found the complicated ones (tarjan's, Vishkin technique). These are complicated and require preprocessing. Any algo based on DFS of the tree or something.
@Anonymous: When you add 16, it should be added as right child of 14 in BST, right? So 12 is the correct answer for LCA of 14 and 16.
This solution doesn't work for all cases.
Add a node with data 16. Find the LCA for 14 , 16. This gives 12, while 8 is the correct solution.
What about LCA for the binary tree (not BST) ?
@Hari Prasad Perabattula: Awesome!! the method given by you works but time and space complexities will be O(n) for skewed BST.
If we are allowed to have extra space, we can follow the following alogorithm:
1). We can find the paths to the two elements. While finding the path to the first element, just store the intermediate nodes in a queue.
2). While traversing the second path, just dequeue until a mismatch is found.
3). The element dequeued just before the mismatch is the LCA.
I think, this can be done in O(logN) time and O(logN) space.
(Note: Works only for BST)
@ben gordon: Thanks very much for pointing out this case. We have made changes to handle this. Program will now correctly find 20 for 22 and 23.
It would stop at 8 before it got to twelve, correctly returning 12.
However, what if the tree is not balanced? If you add 23 to the tree, and give 22 and 23 as input, then I don't think it will correctly find 20
@Hsin-yi Jiang: Thanks for writing to us. We have made corrections.
However, since the algorithm is from top to down, the algorithm doesn't have any problem. It should say: the first time to satisfy the condition n1<n<n2. Thank you for sharing the solution.
Hi, I don't think the n is the only one with the feature n1<n<n2. For instance, with your example, when the question is to find LCA for 4 and 14, 12 is also the one in between 4 and 14. But 12 is not LCA.