PAT 1143 Lowest Common Ancestor (30 分)

题意:

给出一颗二叉搜索树的前序遍历,让你还原这棵树,然后给出k次询问,求结点a和b的LCA。

思路:

常规一点的就是建树后记录每个子节点的父亲以及结点的深度,然后普通LCA跑一下,这里不需要倍增,但是也不能分开得两次dfs(因为退化的二叉搜索树只有一条单链的时候,会炸),得先让两个结点跑到同一层,然后再一起去找爸爸,PAT的题所有操作都暴力就行。

这个题写了两个不易察觉的bug:1. 用map映射的时候,我从零开始了,后面还涉及到查找mp[a]。

                                                     2. 想当然得与上一次的LCA题一样写了两个dfs,只可惜这次数据没让我过

心得:

评测机这门学问还挺深,用clang++交卡我建树,用g++就过了.....所以当出现觉得自己dfs没问题的时候可以试着换一种语言交。

代码:


#include <iostream>
#include <cstring>
#include <stdio.h>
#include <stack>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int N = 1e4+50;
const double eps = 1.e-8;

int n, m, k, cnt, a, b;
struct node {
    int left, right;
    int val;
    int exist;
    int cen;
}edge[N];
map<int, int> mp, rmp;
int vis[N], pre[N], U;

void build (int root, int th, int val, int fa, int zy, int cen) {//clang++卡了我2个小时的建树...
    if (!edge[root].exist) {
        edge[root].val = val;
        edge[root].exist = 1;
        pre[root] = fa;
        edge[root].cen = cen;
        if (zy == 1) edge[fa].right = root;
        else if (zy == 0) edge[fa].left = root;
        return ;
    }
    if (val < edge[root].val) {
        if (edge[root].left != -1) {
            build(edge[root].left, th, val, root, 0, cen+1);
        }
        else {
            build(th, th, val, root, 0, cen+1);
        }
    }
    else {
        if (edge[root].right != -1) {
            build(edge[root].right, th, val, root, 1, cen+1);
        }
        else {
            build(th, th, val, root, 1, cen+1);
        }
    }
}


void slove(int aa, int bb) {//先跑到同一层再去找爸爸。
    int u = mp[aa];
    int v = mp[bb];
    if (edge[u].cen > edge[v].cen) {
        while (edge[u].cen != edge[v].cen) u = pre[u];
        while (u != v) {
            u = pre[u];
            v = pre[v];
        }
        if (u == mp[bb]) printf("%d is an ancestor of %d.\n", bb, aa);
        else printf("LCA of %d and %d is %d.\n", aa, bb, rmp[v]);
    }
    else {
        while (edge[u].cen != edge[v].cen) v = pre[v];
        while (u != v) {
            u = pre[u];
            v = pre[v];
        }
        if (u == mp[aa]) printf("%d is an ancestor of %d.\n", aa, bb);
        else printf("LCA of %d and %d is %d.\n", aa, bb, rmp[v]);
    }
}


int main() {
    cin>>m>>n;
    for (int i = 0; i < N; i++) {
        edge[i].left = -1;
        edge[i].right = -1;
        edge[i].exist = 0;
        pre[i] = i;
    }
    cnt = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &k);
        mp[k] = cnt;
        rmp[cnt] = k;
        cnt++;
        build(0, i, k, 0, -1, 0);
    }

    while (m--) {
        scanf("%d%d", &a, &b);
        if (!mp.count(a) && !mp.count(b)) printf("ERROR: %d and %d are not found.\n", a, b);
        else if (!mp.count(a)) printf("ERROR: %d is not found.\n", a);//注意这里用count查找,因为映射有0.
        else if (!mp.count(b)) printf("ERROR: %d is not found.\n", b);
        else
            slove(a, b);//exist
    }
    return 0;
}

 

上一篇:最近公共祖先 LCA (Lowest Common Ancestors)-树上倍增


下一篇:LeetCode-236 Lowest Common Ancestor of a Binary Tree