class Node {
Node left;
Node right;
int data;
}
If you look at the above structure, there are no parent nodes and the given tree is not a Binary Search Tree which makes the problem all the more complicated.To attack this problem we need to follow the below steps.
- Find the path of the first node using in-order traversal - Cost: O(n)
- Find the path of the second node using in-order traversal - Cost: O(n)
- Put the nodes of the first path in a set - Cost: O(logn)
- For each node in the second path check if it exists in the first path. The matching one would be the Least Common Ancestor - Cost: O(logn)
Now for the java code. I am going to use the Trace Algorithm from the previous post for this solution to make life easier. Hope you were able to learn something.
package dsa.tree;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
/**
* Program to find the Least Common Ancestor without
* for a Binary Tree (Not a BST). The Node does not have
* a parent pointer. The direction of the tree is one sided
* @author Braga
*
*/
public class LCSBinaryTree {
private Node n1,n2;
public static void main(String args[]){
LCSBinaryTree nodeFinder = new LCSBinaryTree();
nodeFinder.find();
}
public void find(){
Tree t = getSampleTree();
Node commonParent = findCommonParent(t,n1,n2);
if(commonParent == null){
System.out.println("Common Parent for "+n1.data+" and "+n2.data+" is null");
}else{
System.out.println("Common Parent for "+n1.data+" and "+n2.data+" is "+commonParent.data);
}
}
private Tree getSampleTree() {
Tree bsTree = new BinarySearchTree();
int randomData[] = {43,887,11,3,8,33,6,0,46,32,78,76,334,45};
for(int i=0;i<randomData.length;i++){
bsTree.add(randomData[i]);
}
n1 = bsTree.search(76);
n2 = bsTree.search(334);
return bsTree;
}
public Node findCommonParent(Tree t, Node node1, Node node2){
TracePath pathTracer = new TracePath();
/**
* If either of the nodes is root, then there is no common
* parent
*/
if(node1.equals(t.getRoot()) || node2.equals(t.getRoot())){
return null;
}
//Using the path tracer, find the path of two nodes in 2*O(n) time.
Stack<Node> path1 = pathTracer.trace(t, node1);
Stack<Node> path2 = pathTracer.trace(t, node2);
//All that is left to do is to find the common parent now.
Set<Node> firstPath = new HashSet<Node>();
for(Node iNode:path1){
firstPath.add(iNode);
}
while(!path2.isEmpty()){
Node currentNode = path2.pop();
if(firstPath.contains(currentNode)){
if(!path2.isEmpty() && firstPath.contains(currentNode = path2.peek())){
return path2.peek();
}
return currentNode;
}
}
return null;
}
}
//SAMPLE OUTPUTS
//Common Parent for 887 and 334 is 43
//Common Parent for 43 and 334 is null
//Common Parent for 6 and 334 is 43
//Common Parent for 76 and 334 is 46
Cheers,Bragaadeesh.
