PAT---A1151 LCA in a Binary Tree (30分)

题意

给出一棵二叉树的中序和先序遍历,输入两个key a和b,求a和b的lca,即最近的祖先节点。

思路

此题参考了别人的思路。首先处理not found的情况,然后处理两个节点都在二叉树的情况。从根节点开始,

  1. 如果根节点在a和b之间,说明根节点就是答案
  2. 如果根节点是a和b中的一个,得到答案
  3. 如果根节点在a和b的左边,则将根节点变为右子树的根节点,重复上述过程
  4. 如果根节点在a和b的右边,则将根节点变为左子树的根节点,重复上述过程。

用一个map来存储每个key对应的节点在中序遍历数组中的位置。
然而用map有一个case会超时(限制为1000ms),改为unordered_map了之后就在300ms以内了,我很疑惑差距真的这么大吗?

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
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.
#include "bits/stdc++.h"
using namespace std;
vector<int> in,pre;
unordered_map<int,int> pos;
int t1,t2;
void lca(int rootId,int inL,int inR){
    if (inL > inR ) return;
    if (pre[rootId] == t1 || pre[rootId] == t2){
        printf("%d is an ancestor of %d.\n",pre[rootId]==t1 ? t1:t2,pre[rootId]==t1 ? t2:t1);
    } else {
        int numL = pos[pre[rootId]] - inL;
        int rootId_in = pos[pre[rootId]];
        if (rootId_in > max(pos[t1],pos[t2])) lca(rootId+1,inL,rootId_in-1);
        else if (rootId_in < min(pos[t1],pos[t2])) lca(rootId+1+numL ,rootId_in+1,inR);
        else {
            printf("LCA of %d and %d is %d.\n",t1,t2,pre[rootId]);
        }
    }
}
void lca(int a,int b){
    t1 = a, t2 = b;
    lca(0,0,in.size()-1);
}
int main(){
//     freopen("input.txt","r",stdin);
    int m, n; scanf("%d%d",&m,&n); in.resize(n), pre.resize(n);
    for(int i=0;i<n;i++) scanf("%d",&in[i]), pos[in[i]] = i;
    for(int i=0;i<n;i++) scanf("%d",&pre[i]);
    for (int i = 0; i < m; ++i) {
        int a, b; scanf("%d%d",&a,&b);
        if (! pos.count(a) && ! pos.count(b)) printf("ERROR: %d and %d are not found.\n",a,b);
        else if (! pos.count(a) || !pos.count(b)) printf("ERROR: %d is not found.\n",pos.count(a) ? b : a);
        else lca(a,b);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值