题目描述
给定一棵二叉搜索树的先序遍历序列,要求你找出任意两结点的最近公共祖先结点(简称 LCA)。
输入
输入的第一行给出两个正整数:待查询的结点对数 M(≤ 1 000)和二叉搜索树中结点个数 N(≤ 10 000)。随后一行给出 N 个不同的整数,为二叉搜索树的先序遍历序列。最后 M 行,每行给出一对整数键值 U 和 V。所有键值都在整型int范围内。
输出
对每一对给定的 U 和 V,如果找到 A
是它们的最近公共祖先结点的键值,则在一行中输出 LCA of U and V is A.
。但如果 U 和 V 中的一个结点是另一个结点的祖先,则在一行中输出 X is an ancestor of Y.
,其中 X
是那个祖先结点的键值,Y
是另一个键值。如果 二叉搜索树中找不到以 U 或 V 为键值的结点,则输出 ERROR: U is not found.
或者 ERROR: V is not found.
,或者 ERROR: U and V are not found.
。
输入样例
6 8
6 3 1 2 5 4 8 7
2 5
8 7
1 9
12 -3
0 8
99 99
输出样例
LCA of 2 and 5 is 3.
8 is an ancestor of 7.
ERROR: 9 is not found.
ERROR: 12 and -3 are not found.
ERROR: 0 is not found.
ERROR: 99 and 99 are not found.
思路分析
首先判断u和v是否在树中。有不在的就输出ERROR的三种情况之一。
若都在树中, 把每个结点的所有父亲都用数组或队列存起来。若u和v都在树中,找u的父亲中有没有v。输出 X is an ancestor of Y.
,其中 X
是那个祖先结点的键值,Y
是另一个键值。没有就u和v父亲数组中相同的元素,倒着找,找到的就是最近的公共祖先。那么问题来了,如何找到每个结点的父亲呢?因为给出的是二叉搜索树先序遍历的结果,所以第一个是根,第二个到比他大的数之前的都是左子树,比他大的到最后都是右子树。那么第二个到最后一个都可以添加一个父亲,添加根。再递归地遍历左子树和右子树,树种除了根的每一个结点都把根结点当作父亲。
AC代码
#include<iostream>
#include<queue>
using namespace std;
int a[100];
queue<int> parent[100];
int n;
int find(int x) {
for (int i = 0; i < n; i++) {
if (a[i] == x) return 1;
}
return 0;
}
void if_tree(int start, int end) {
if (start >= end) return ;
for (int i = start + 1; i < end; i++)
parent[i].push(a[start]);
int center = start + 1;
while (a[center] < a[start]) {
if (center >= n) break;
center++;
}
if_tree(center, end); //右子树
if_tree(start + 1, center); //左子树
return ;
}
int main() {
int m, u, v;
cin >> m >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
while (m--) {
cin >> u >> v;
int find1 = 0, find2 = 0;
find1 = find(u);
find2 = find(v);
if (find1 + find2 == 0) {
cout << "ERROR: " << u << " and " << v << " are not found." << endl;
} else if (find1 == 0 && find2 == 1) {
cout << "ERROR: " << u << " is not found." << endl;
} else if (find1 == 1 && find2 == 0) {
cout << "ERROR: " << v << " is not found." << endl;
} else {
if_tree(0,n);
int tag=0;
int uindex, vindex;
for (int i = 0; i < n; i++) {
if (u == a[i]) uindex = i;
if (v == a[i]) vindex = i;
}
queue<int> uu = parent[uindex];
queue<int> vv = parent[vindex];
int usize = uu.size();
int vsize = vv.size();
// cout<<"u有几个父亲:"<<usize<<endl;
// cout<<"v有几个父亲:"<<vsize<<endl;
while (!parent[uindex].empty()) {
if (parent[uindex].front() == v) {
tag = 1;
break;
}
parent[uindex].pop();
}
while (!parent[vindex].empty()) {
if (parent[vindex].front() == u) {
tag = 2;
break;
}
parent[vindex].pop();
}
if (tag == 1) {
cout << v << " is an ancestor of " << u << "." << endl;
} else if (tag == 2) {
cout << u << " is an ancestor of " << v << "." << endl;
} else {
int uuu[usize];
for (int i = 0; i < usize; i++) {
uuu[i] = uu.front();
uu.pop();
}
int vvv[vsize];
for (int i = 0; i < vsize; i++) {
vvv[i] = vv.front();
vv.pop();
}
int tag = 0, result;
for (int i = usize - 1; i >= 0; i--) {
for (int j = vsize - 1; j >= 0; j--) {
if (uuu[i] == vvv[j]) {
result = uuu[i];
tag = 1;
break;
}
}
if (tag == 1) break;
}
cout << "LCA of " << u << " and " << v << " is " << result << "." << endl;
}
}
}
return 0;
}
有问题欢迎指正!