1. What is the most recent common ancestor?
LCA is the abbreviation of Lowest Common Ancestor.
For two nodes u, v of a rooted tree T, the nearest common ancestor LCA (T, u, v) represents a node x.
LCA(5,6) = 2
LCA(7,12) = 3
LCA(2,1)=1
2. Simple solution of common ancestors
- The two nodes are first adjusted to the same depth
- Each time two points jump up one level at the same time, when the two points meet, it is the LCA of the two points.
For a set of queries, the time complexity is O(N)
It requires deep traversal and then constructs such a table
Assume that LCA(D,G) is found.
The first step: first determine that the depth of D is 3 and the depth of G is 1.
The second step is to move D one step up according to the parent node array, which is node B.
The third step: At this time, the depth B is still different between 2 and 1. You need to continue upward, that is, A. At this time, the depths of A and G are consistent. Step 4:
Determine whether the parent node of A and the parent node of G are consistent. If they are consistent, find it. If they are inconsistent, they will be raised one step at the same time, and this cycle will continue until the two parent nodes are the same for the first time.
3. Recursive solution
There are the following pictures
4. Code
The following code constructs the following tree, and implements the naive method and the recursive method respectively.
#include<iostream>
using namespace std;
using ElemType = char;
typedef struct BiTNode
{
ElemType data;
int nIndex;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode, * BiTree;
int arrayD[100] = {
-1 };
int arrayF[100] = {
-1 };
void DFS(BiTNode* tree, int nd, int nf)
{
if (tree)
{
DFS(tree->lchild, nd + 1, tree->nIndex);
arrayD[tree->nIndex] = nd;
arrayF[tree->nIndex] = nf;
DFS(tree->rchild, nd + 1, tree->nIndex);
}
}
int LCA1(int u, int v)
{
if (arrayD[u] < arrayD[v])
{
swap(u, v);
}
if (arrayD[u] > arrayD[v] && arrayF[u] != v)
{
while (arrayD[u] != arrayD[v])
{
u = arrayF[u];
}
while (arrayF[u] != arrayF[v])
{
u = arrayF[u];
v = arrayF[v];
}
}
return arrayF[u];
}
BiTNode* LCA2(BiTNode *pRoot,BiTNode *p,BiTNode *q)
{
if (pRoot == p|| pRoot == q || pRoot == NULL)
{
return pRoot;
}
BiTNode* pLeft = LCA2(pRoot->lchild, p, q);
BiTNode* pRight = LCA2(pRoot->rchild, p, q);
if (pLeft && pRight)
{
return pRoot;
}
else if (pLeft)
{
return pLeft;
}
else if (pRight)
{
return pRight;
}
else
{
return NULL;
}
}
int main()
{
BiTNode b1, b2, b3, b4, b5, b6, b7;
memset(&b1, 0, sizeof(BiTNode));
memset(&b2, 0, sizeof(BiTNode));
memset(&b3, 0, sizeof(BiTNode));
memset(&b4, 0, sizeof(BiTNode));
memset(&b5, 0, sizeof(BiTNode));
memset(&b6, 0, sizeof(BiTNode));
memset(&b7, 0, sizeof(BiTNode));
b1.nIndex = 0; b1.data = 'A';
b2.nIndex = 1; b2.data = 'B';
b3.nIndex = 2; b3.data = 'C';
b4.nIndex = 3; b4.data = 'D';
b5.nIndex = 4; b5.data = 'E';
b6.nIndex = 5; b6.data = 'F';
b7.nIndex = 6; b7.data = 'G';
//构建树关系
b1.lchild = &b2;
b1.rchild = &b3;
b2.lchild = &b4;
b2.rchild = &b5;
//根
b6.lchild = &b1;
b6.rchild = &b7;
cout << "LCA1:\n";
DFS(&b6, 0, -1);
int nIndex = LCA1(b1.nIndex, b2.nIndex);
if (nIndex >= 0)
{
printf("LCA(%c,%c)= index(%d)\n", b1.data, b2.data, nIndex);
}
nIndex = LCA1(b5.nIndex, b7.nIndex);
if (nIndex >= 0)
{
printf("LCA(%c,%c)= index(%d)\n", b5.data, b7.data, nIndex);
}
//LCA2
cout << "LCA2:\n";
BiTNode *pLCA = LCA2(&b6, &b1, &b2);
if (pLCA)
{
printf("LCA(%c,%c)= %c\n",b1.data,b2.data, pLCA->data);
}
pLCA = LCA2(&b6, &b5, &b7);
if (pLCA)
{
printf("LCA(%c,%c)= %c\n", b5.data, b7.data, pLCA->data);
}
system("pause");
}
result: