一、题目描述
原题链接
The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U and V as descendants.
Given any two nodes in a binary tree, you are supposed to find their LCA.
Input Specification:
Output Specification:
Sample Input:
6 8
7 2 3 4 6 5 1 8
5 3 7 2 6 4 8 1
2 6
8 1
7 9
12 -3
0 8
99 99
Sample Output:
LCA of 2 and 6 is 3.
8 is an ancestor of 1.
ERROR: 9 is not found.
ERROR: 12 and -3 are not found.
ERROR: 0 is not found.
ERROR: 99 and 99 are not found.
二、解题思路
这道题目代码不长,涉及到基本的LCA算法。事实上,我们只要弄明白,要找到两个结点的LCA,关键是把从根结点出发的左右子树分开,这个就要用到中序遍历序列了,前序遍历序列则帮助我们找到根结点。弄清楚原理之后不难,但是还是需要花时间理解一下的,详情见代码注释。
三、AC代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<unordered_map>
#include<algorithm>
using namespace std;
unordered_map<int, int> pos;
int pre[10010], in[10010];
void lca(int inL, int inR, int preRoot, int a, int b)
{
if(inL > inR) return; //递归边界
int inRoot = pos[pre[preRoot]]; //找到中序遍历序列中的根节点
if(pos[a] < inRoot && pos[b] < inRoot) //两个结点的位置在当前根结点的左子树
lca(inL, inRoot-1, preRoot+1, a, b); //递归查询左子树
//当前根结点即为LCA
else if((pos[a] < inRoot && pos[b] > inRoot) || (pos[a] > inRoot && pos[b] < inRoot)) printf("LCA of %d and %d is %d.\n", a, b, pre[preRoot]);
//当前根结点为a或b
else if(pos[a] == inRoot || pos[b] == inRoot) pos[a] == inRoot ? printf("%d is an ancestor of %d.\n", a, b) : printf("%d is an ancestor of %d.\n", b, a);
//递归查询右子树
else lca(inRoot + 1, inR, preRoot + inRoot - inL + 1, a, b);
}
int main()
{
int M, N, a, b;
scanf("%d%d", &M, &N);
for(int i=1; i<=N; i++)
{
scanf("%d", &in[i]);
pos[in[i]] = i;
}
for(int i=1; i<=N; i++)
scanf("%d", &pre[i]); //存放先序遍历序列
for(int i=0; i<M; i++)
{
scanf("%d%d", &a, &b);
if(pos[a] == 0 && pos[b] == 0)
printf("ERROR: %d and %d are not found.\n", a, b);
else if(pos[a] == 0 || pos[b] == 0)
pos[a] == 0 ? printf("ERROR: %d is not found.\n", a) : printf("ERROR: %d is not found.\n", b);
else lca(1, N, 1, a, b);
}
return 0;
}