If it is full binary tree with children of node x as 2*x and 2*x+1 than there is a faster way to do it
int get_bits(unsigned int x) {
int high = 31;
int low = 0,mid;
while(high>=low) {
mid = (high+low)/2;
if(1<<mid==x)
return mid+1;
if(1<<mid<x) {
low = mid+1;
}
else {
high = mid-1;
}
}
if(1<<mid>x)
return mid;
return mid+1;
}
unsigned int Common_Ancestor(unsigned int x,unsigned int y) {
int xbits = get_bits(x);
int ybits = get_bits(y);
int diff,kbits;
unsigned int k;
if(xbits>ybits) {
diff = xbits-ybits;
x = x >> diff;
}
else if(xbits<ybits) {
diff = ybits-xbits;
y = y >> diff;
}
k = x^y;
kbits = get_bits(k);
return y>>kbits;
}
How does it work
- get bits needed to represent x & y which using binary search is O(log(32))
- the common prefix of binary notation of x & y is the common ancestor
- whichever is represented by larger no of bits is brought to same bit by k >> diff
- k = x^y erazes common prefix of x & y
- find bits representing the remaining suffix
- shift x or y by suffix bits to get common prefix which is the common ancestor.
This works because basically divide the larger number by two recursively until both numbers are equal. That number is the common ancestor. Dividing is effectively the right shift opearation. So we need to find common prefix of two numbers to find the nearest ancestor