题目大意:给出二叉树的先序和中序遍历,输出节点U和V的最低公共祖先。
可以直接用PAT A1143 Lowest Common Ancestor的第一种方法做,先建树,再从根节点出发dfs找到到达节点U和V的两条路径,之后找到两条路径的分叉点,就是最低公共祖先。
AC代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstring>
using namespace std;
vector<int> pre;
unordered_map<int, int> in;
struct Node
{
int data;
Node* left;
Node* right;
Node(int data): data(data), left(NULL), right(NULL){};
};
void createFromPreIn(Node* &node, int prel, int prer, int inl, int inr)
{
if(prel > prer) return;
if(node == NULL) node = new Node(pre[prel]);
int index = in[pre[prel]], leftNum = index - inl;
createFromPreIn(node->left, prel+1, prel + leftNum, inl, index - 1);
createFromPreIn(node->right, prel + leftNum + 1, prer, index + 1, inr);
}
void dfs(Node* node, int u, vector<int> &path, vector<int>& tmpPath, bool &flag)
{
if(flag || !node) return;
if(node->data == u)
{
tmpPath.push_back(u);
path = tmpPath;
flag = true;
tmpPath.pop_back();
return;
}
tmpPath.push_back(node->data);
dfs(node->left, u, path, tmpPath, flag);
dfs(node->right, u, path, tmpPath, flag);
tmpPath.pop_back();
}
int main()
{
int M, N;
scanf("%d%d", &M, &N);
unordered_set<int> st;
for (int i = 0; i < N; ++i)
{
int data;
scanf("%d", &data);
st.insert(data);
in[data] = i;
}
pre.resize(N);
for (int i = 0; i < N; ++i)
{
scanf("%d", &pre[i]);
}
Node* root = NULL;
createFromPreIn(root, 0, N-1, 0, N-1);
for (int i = 0; i < M; ++i)
{
int u, v;
scanf("%d%d", &u, &v);
if(st.count(u) == 0 && st.count(v) > 0) printf("ERROR: %d is not found.\n", u);
else if(st.count(u) > 0 && st.count(v) == 0) printf("ERROR: %d is not found.\n", v);
else if(st.count(u) == 0 && st.count(v) == 0) printf("ERROR: %d and %d are not found.\n", u, v);
else
{
vector<int> uPath, vPath, tmpPath1, tmpPath2;
bool uFlag = false, vFlag = false;
dfs(root, u, uPath, tmpPath1, uFlag);
dfs(root, v, vPath, tmpPath2, vFlag);
int j;
for (j = 0; j < uPath.size() && j < vPath.size(); ++j)
{
if(uPath[j] != vPath[j]) break;
}
if(j < uPath.size() && j < vPath.size()) printf("LCA of %d and %d is %d.\n", u, v, uPath[j-1]);
else if(j == uPath.size()) printf("%d is an ancestor of %d.\n", u, v);
else if(j == vPath.size()) printf("%d is an ancestor of %d.\n", v, u);
}
}
return 0;
}