[1] / \ [2] [3] / \ / \ [4] [5] [9] [10] / / \ [8] [6] [7]
say
n1,n2 = 8,3 => Common Ancestor =1
n1,n2 = 8,6 => Common Ancestor =2
n1,n2 = 7,6 => Common Ancestor =5
Method 1)
logic : when traversing from root node,
keep paths for both n1 & n2.
ex1:
p1 : 1,2,4,8
p2 : 1,3
last common value in path is LCA=1
ex2:
p1 : 1,2,4,8
p2 : 1,2,5,6
last common value in path is LCA=2
Algorithm :
FindPath ( root, vector<int> &path, int N ) { path.push_back(root->key) if(root->key = N) return 1; if ( (root->left && findPath( root->left, path, N) ) | | (root->right && findPath( root->right, path, N) ) return 1; path.pop_back(); //if path is not in this subtree return 0; } CommAncsestor( root , n1, n2 ){ vector <int> p1,p2; int i; if (!findPath(root, path1, n1) || !findPath(root, path2, n2)) return -1; for(i=0; i< path1.size() && i<path2.size(); i++){ if(path1[i] != path2[i]) break; } return path1[i-1]; }
Method 2)
Now think for a way where
ex:1)
when n1=8, n2=3.
while we call from root =1 , 8 will return from left subtree and 3 will return from right subtree.
so we can say CommonAncestor is 1.
ex:2) n1=8, n2= 6
for previous call, 8 and 6 will be returned from leftsubtree, while in right subtree 6 is not there , hence it will return NULL.
so if one subtree return Null, go and search in similar way as ex:1) in other subtree
so here for
for root=1, Leftsubtree=8, rightsubtree=NULL.
call leftsubtree
root = 2 its leftsubtree return 8, and rightsubtree returns 6. hence Common Ancestor is 2.
struct Node *findLCA(struct Node* root, int n1, int n2) { if (root == NULL) return NULL; if (root->key == n1 || root->key == n2) return root; Node *left_lca = findLCA(root->left, n1, n2); Node *right_lca = findLCA(root->right, n1, n2); if (left_lca && right_lca) return root; return (left_lca != NULL)? left_lca: right_lca; }
Working Code can be Found at http://ideone.com/J7gzfk
Least Common Ancestor LCA of Binary Search Tree
Say binary search is as given below
[7] / \ [6] [9] / / \ [5] [8] [10]
n1,n2 = 8,10 => Common Ancestor =9
n1,n2 = 8,6 => Common Ancestor =7
n1,n2 = 5,6 => Common Ancestor =6
as this tree is BST with property that leftSubTree < Parent < RightSubTree
we can use it to get CommonAncsestor.
now as we start traversing from root.
if root < n1 & root < n2 then CommonAncestor lies in Right sub tree of Root.
say in example 1) with 8,10.
if root > n1 & root > n2 then CommonAncestor lies in left sub tree of root
say in example 3) with 5,6
else root itself is CommonAncestor when root < n1 but root > n2. or root > n1 but root < n2
say in example 2) with 6,8.
struct node *CommonAncestor (struct node* root, int n1, int n2) { if (root == NULL) return NULL; if (root->data > n1 && root->data > n2) return CommonAncestor(root->left, n1, n2); else if (root->data < n1 && root->data < n2) return CommonAncestor(root->right, n1, n2); return root; }
Time complexity of above solution is O(h) where h is height of tree.
Space Complexity O(h) due to function call stack for recursive function calls.
We can avoid extra space using iterative solution.
Algorithm for iterative
struct node *CommonAncestor(struct node* root, int n1, int n2) { while (root != NULL) { if (root->data > n1 && root->data > n2) root = root->left; else if (root->data < n1 && root->data < n2) root = root->right; else break; } return root; }
Working Code :
// A recursive C program to find LCA of two nodes n1 and n2 By Gohired.in #include <stdio.h> #include <stdlib.h> struct node { int data; struct node* left, *right; }; struct node *commonAncestor2(struct node* root, int n1, int n2) { while (root != NULL) { if (root->data > n1 && root->data > n2) root = root->left; else if (root->data < n1 && root->data < n2) root = root->right; else break; } return root; } struct node *commonAncestor(struct node* root, int n1, int n2) { if (root == NULL) return NULL; if (root->data > n1 && root->data > n2) return commonAncestor(root->left, n1, n2); else if (root->data < n1 && root->data < n2) return commonAncestor(root->right, n1, n2); return root; } struct node* newNode(int data) { struct node* node = (struct node*)malloc(sizeof(struct node)); node->data = data; node->left = node->right = NULL; return(node); } int main() { struct node *root = newNode(20); root->left = newNode(8); root->right = newNode(22); root->left->left = newNode(4); root->left->right = newNode(12); root->left->right->left = newNode(10); root->left->right->right = newNode(14); int n1 = 10, n2 = 14; struct node *t; t = commonAncestor(root, n1, n2); printf("LCA of %d and %d is %d \n", n1, n2, t->data); n1 = 14, n2 = 8; t = commonAncestor(root, n1, n2); printf("LCA of %d and %d is %d \n", n1, n2, t->data); n1 = 10, n2 = 22; t = commonAncestor(root, n1, n2); printf("LCA of %d and %d is %d \n", n1, n2, t->data); printf("------Out put with Iterative Mehtod --------\n"); n1 = 10, n2 = 14; t = commonAncestor2(root, n1, n2); printf("LCA of %d and %d is %d \n", n1, n2, t->data); n1 = 14, n2 = 8; t = commonAncestor2(root, n1, n2); printf("LCA of %d and %d is %d \n", n1, n2, t->data); n1 = 10, n2 = 22; t = commonAncestor2(root, n1, n2); printf("LCA of %d and %d is %d \n", n1, n2, t->data); getchar(); return 0; }
Output
LCA of 10 and 14 is 12
LCA of 14 and 8 is 8
LCA of 10 and 22 is 20
——Out put with Iterative Mehtod ——–
LCA of 10 and 14 is 12
LCA of 14 and 8 is 8
LCA of 10 and 22 is 20
Working Code http://ideone.com/v1ziEj