题目链接
https://pintia.cn/problem-sets/994805342720868352/problems/994805343727501312
题解
题目要求
-
最近公共祖先(LCA,The lowest common ancestor)
在一颗树中,结点U和V的LCA是U和V为其后代的深度最大的结点。
-
二叉搜索树(BST,binary search tree)
- 树中的每个结点的值都大于其左子树中结点的值
- 树中的每个结点的值都不超过其右子树中结点的值
- 每个结点的左子树和右子树都是二叉搜索树
给定一个二叉搜索树中的任意两个结点,请找到他们的LCA。
-
输入
- M:正整数,不超过1000,需要测试的结点对的数量
- N:正整数,不超过10000,二叉搜索树中结点的数量
- N个结点(互异):按照先序遍历的顺序给出,值都在int范围内
- M个结点对
-
输出
对于每个结点对,判断结点对中每个结点是否存在,如果都存在则找到他们的LCA。
解题思路
不需建树
-
判断结点是否在树中
读取树的先序遍历时使用map记录一个结点是否在树中
-
寻找LCA
根据BST的性质,如果一个结点的值处于u和v的值之间,那这个结点就是u和v的LCA。
这道题涉及LCA,也可以看看另外一道题:PAT甲级1151 LCA in a Binary Tree
代码
// Problem: PAT Advanced 1143
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805343727501312
// Tags: Tree BST LCA map
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int main()
{
int m, n, u, v, a;
scanf("%d %d", &m, &n);
vector<int> preOrder(n);
map<int, bool> exists;
for (int i = 0; i < n; i++){ // 读取先序遍历结果并记录结点是否出现过
scanf("%d", &preOrder[i]);
exists[preOrder[i]] = true;
}
while (m--) { // m个结点对
scanf("%d %d", &u, &v);
for (int i = 0; i < n; i++){ // 寻找LCA
a = preOrder[i];
if (u < a && v > a || v < a && u > a || (a == u) || (a == v) )
break;
}
if (exists[u] == false && exists[v] == false)
printf("ERROR: %d and %d are not found.
", u, v);
else if (exists[u] == false || exists[v] == false)
printf("ERROR: %d is not found.
", exists[u]==false ? u : v);
else if (a == u || a == v)
printf("%d is an ancestor of %d.
", a, a == u ? v : u);
else
printf("LCA of %d and %d is %d.
", u, v, a);
}
return 0;
}
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!