PAT-A 1151 LCA in a Binary Tree (30 分)

树中两个结点 U 和 V 的最低公共祖先(LCA)是指同时具有 U 和 V 作为后代的最深结点。

给定二叉树中的任何两个结点,请你找到它们的 LCA。

输入格式
第一行包含两个整数 M 和 N,分别表示询问结点对数以及二叉树中的结点数量。

接下来两行,每行包含 N 个不同的整数,分别表示二叉树的中序和前序遍历。

保证二叉树可由给定遍历序列唯一确定。

接下来 M 行,每行包含两个整数 U 和 V,表示一组询问。

所有结点权值均在 int 范围内。

输出格式
对于每对给定的 U 和 V,输出一行结果。

如果 U 和 V 的 LCA 是 A,且 A 不是 U 或 V,则输出 LCA of U and V is A.。

如果 U 和 V 的 LCA 是 A,且 A 是 U 或 V 中的一个,则输出 X is an ancestor of Y.,其中 X 表示 A,Y 表示另一个结点。

如果 U 或 V 没有在二叉树中找到,则输出 ERROR: U is not found. 或 ERROR: V is not found. 或 ERROR: U and V are not found.。

数据范围
1≤M≤1000,
1≤N≤10000
输入样例:
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
输出样例:
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的题,但是这次的树并不是直接是二叉搜索树。
我们可以中序遍历每个节点,人为的给这每个节点添加一个数做标记,这样这棵树就具有了类似二叉搜索树的性质,而我们通过对添加的标记进行比较,就可以达到判断向左走还是向右走的目的。

#include <bits/stdc++.h>

using namespace std;
struct node
{
    int data;
    struct node*l,*r;
}a[10101];
int n,m,k;
unordered_map<int,int> mp;
unordered_map<int,int> path;
int pre[10100],inorder[10010];
int cnt=1;
struct node*create(int h1,int h2,int len)//前、中、长度
{
    if(len==0)
    return NULL;
    struct node*p;
    p = new node;
    p->data = pre[h1];
    int i = mp[pre[h1]];
    int l1 = i-h2;
    int l2 = len-1-l1;
    p->l = create(h1+1,h2,l1);
    p->r = create(h1+1+l1,i+1,l2);
    return p;
}
void getid(struct node*root)
{
    if(root)
    {
        getid(root->l);
        path[root->data] = cnt++;
        getid(root->r);
    }
}
int main()
{
    cin >>m >>n;
    for(int i=1;i<=n;i++)
    cin >>inorder[i],mp[inorder[i]] = i;
    for(int i=1;i<=n;i++)
    cin >>pre[i];
    struct node*root = create(1,1,n);
    getid(root);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin >> x >>y;
        if(!mp.count(x)&&!mp.count(y))
        printf("ERROR: %d and %d are not found.\n",x,y);
        else if(!mp.count(x))
         printf("ERROR: %d is not found.\n",x);
        else if(!mp.count(y))
         printf("ERROR: %d is not found.\n",y);
        else
        {
            struct node*p=root;
            int xx = path[x];
            int yy = path[y];
            while((xx<path[p->data]&&yy<path[p->data])||(xx>path[p->data]&&yy>path[p->data]))
            {
              if(xx<path[p->data]&&yy<path[p->data])
              p=p->l;
              else if(xx>path[p->data]&&yy>path[p->data])
              p=p->r;  
            }
            if(p->data == x)
            printf("%d is an ancestor of %d.\n",x,y);
            else if(p->data == y)
            printf("%d is an ancestor of %d.\n",y,x);
            else
            printf("LCA of %d and %d is %d.\n",x,y,p->data);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值