To find the first common ancestor of two nodes in a tree where nodes maintain a reference to their parent, follow these steps:
- Calculate Depth: Determine the depth of both target nodes by traversing up to the root using the parent reference.
- Align Depths: Calculate the difference in depth between the two nodes. Move the deeper node up the tree (towards the root) until both nodes are at the same depth.
- Simultaneous Ascent: Move both nodes up to their respective parents one step at a time. The first node they both encounter that is identical is the First Common Ancestor.
package graphs;
import graphs.commons.BidirectionalTree;
class FirstCommonAncestor {
// Returns the depth of a node relative to the root
static Integer depth(BidirectionalTree tree) {
BidirectionalTree current = tree;
int count = 0;
while (current.parent != null) {
current = current.parent;
count++;
}
return count;
}
// Moves a node up the tree by a specified number of levels
static BidirectionalTree goUpBy(BidirectionalTree tree, int times) {
BidirectionalTree current = tree;
for (int i = 1; i <= Math.abs(times); i++) {
current = current.parent;
}
return current;
}
// Finds the first common ancestor of two nodes at the same depth
static BidirectionalTree commonAncestor(BidirectionalTree t1, BidirectionalTree t2) {
BidirectionalTree current1 = t1;
BidirectionalTree current2 = t2;
while (current1 != current2) {
current1 = current1.parent;
current2 = current2.parent;
}
return current1;
}
public static void main(final String[] args) {
// Example setup: BidirectionalTree(parent, data)
final BidirectionalTree tree = new BidirectionalTree(null, 10);
tree.left = new BidirectionalTree(tree, 20);
tree.right = new BidirectionalTree(tree, 80);
// ... tree construction ...
BidirectionalTree p = // node 1
BidirectionalTree q = // node 2
int delta = depth(p) - depth(q);
BidirectionalTree t1 = p;
BidirectionalTree t2 = q;
if (delta < 0) {
t2 = goUpBy(q, delta);
} else if (delta > 0) {
t1 = goUpBy(p, delta);
}
BidirectionalTree lca = commonAncestor(t1, t2);
System.out.println("Common Ancestor: " + lca.data);
}
}