PAT 1151 LCA in a Binary Tree (30分) (两种解法)

PAT 1151 LCA in a Binary Tree (30分) (两种解法)

题目链接

分析

这个和PAT 1143是类似的题目,区别就是PAT 1143是二叉搜索树,而这一题就是个普通的二叉树。
第一种解法必然是无脑的重建树,然后找U和V的祖先。

解法1

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#define MAX 10100
using namespace std;

int N,M;
int pre[MAX];
int in[MAX];
map<int,int> pos;
vector<int> ancestor[MAX];
int father[MAX];
struct Node
{
    int val;
    int father = -1;
}node[MAX];
void rebuild(int iL,int iR,int pL,int pR,int rindex)
{
    //cout<<iL<<" "<<iR<<" "<<pL<<" "<<pR<<endl;
    if(iL>iR||pL>pR)
        return;
    int root = pre[pL];
    int m = pos[root];
    node[m].father = rindex;
    rebuild(iL,m-1,pL+1,pL+m-iL,m);
    rebuild(m+1,iR,pL+m-iL+1,pR,m);
}
int main()
{
    scanf("%d%d",&M,&N);
    for(int i=0;i<N;i++)
    {
        scanf("%d",&in[i]);
        node[i].val = in[i];
        pos[node[i].val] = i;
    }
    for(int i=0;i<N;i++)
        scanf("%d",&pre[i]);
    rebuild(0,N-1,0,N-1,N);
    for(int i=0;i<M;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(pos.find(a)==pos.end())
        {
            if(pos.find(b)==pos.end())
            {
                printf("ERROR: %d and %d are not found.\n",a,b);
            }
            else{
                printf("ERROR: %d is not found.\n",a);
            }
        }
        else if(pos.find(b)==pos.end())
        {
            printf("ERROR: %d is not found.\n",b);
        }
        else{
            if(a==b)
            {
                printf("%d is an ancestor of %d.\n",a,b);
                continue;
            }
            int aindex = pos[a];
            int bindex = pos[b];
            int ra = aindex;
            int rb = bindex;
            vector<int> afa, bfa;
            bool flag = true;
            while(ra!=-1)
            {
                afa.push_back(ra);
                if(node[ra].father == bindex)
                {
                    flag = false;
                    printf("%d is an ancestor of %d.\n",b, a);
                    break;
                }
                ra = node[ra].father;

            }
            while(flag&&rb!=-1)
            {
                bfa.push_back(rb);
                if(node[rb].father == aindex)
                {
                    printf("%d is an ancestor of %d.\n",a, b);
                    flag = false;
                    break;
                }
                rb = node[rb].father;
            }
            if(flag)
            {
                int ai = afa.size()-1;
                int bj = bfa.size()-1;
                while(ai>=0&&bj>=0&&afa[ai]==bfa[bj])
                {
                    ai--;
                    bj--;
                }
                printf("LCA of %d and %d is %d.\n",a, b, in[afa[ai+1]]);
            }
        }
    }
    return 0;
}

再次分析

这题本质上和PAT 1143没什么不同。普通的二叉搜索树用一个字典pos映射一下就可转换成二叉搜索树,然后就可以用老方法求解啦。PAT 1143题解

1、在中序遍历中,最近公共祖先的位置一定在U和V之间。
2、在前序遍历中,是按该节点、左子节点、右子节点的顺序遍历的:
所以,遍历前序遍历数组,设序号为i,第一个满足(pos[pre[i]]>=U&&pos[pre[i]]<=V)||(pos[pre[i]]>=V&&pos[pre[i]]<=U)pos[pre[i]]就是最近公共祖先中序遍历的下标。

解法2

#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#define MAX 10100
using namespace std;

int M,N;
int pre[MAX];
int in[MAX];
map<int,int> pos;
int main()
{
    scanf("%d%d",&M,&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 U,V;
        scanf("%d%d",&U,&V);
        if(pos.find(U)==pos.end())
        {
            if(pos.find(V)==pos.end())
            {
                printf("ERROR: %d and %d are not found.\n",U,V);
            }
            else printf("ERROR: %d is not found.\n",U);
        }
        else if(pos.find(V)==pos.end())
            printf("ERROR: %d is not found.\n",V);
        else{
            int ans = 0;
            int posU = pos[U];
            int posV = pos[V];
            for(int i=0;i<N;i++)
            {
                int p = pos[pre[i]];
                if((p>=posU&&p<=posV)||(p>=posV&&p<=posU))
                {
                    ans = p;
                    break;
                }
            }
            ans = in[ans];
            if(ans==U)
                printf("%d is an ancestor of %d.\n",U,V);
            else if(ans==V)
                printf("%d is an ancestor of %d.\n",V,U);
            else printf("LCA of %d and %d is %d.\n",U,V,ans);
        }
    }
    return 0;
}

更多二叉树题解

PAT二叉树题目总结

原创文章 39 获赞 5 访问量 4926

猜你喜欢

转载自blog.csdn.net/q1072118803/article/details/104993652