PAT 1143 Lowest Common Ancestor (30分)(两种解法)

PAT 1143. Lowest Common Ancestor (30分)

题目链接

分析

给一个二叉搜索树的前序遍历数组,让求最近公共祖先。
首先最容易想到的办法就是:重建树,然后找U和V的祖先,分别得到U和V的祖先数组。同时从后到前遍历U和V的祖先数组,设为ancU, ancV,最后一个满足ancU==ancV的就是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)
{
    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",&pre[i]);
        in[i] = pre[i];
    }
    sort(in,in+N);
    for(int i=0;i<N;i++)
    {
        node[i].val = in[i];
        pos[node[i].val] = i;
    }
    rebuild(0,N-1,0,N-1,-1);
    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;
}

再次分析

解法1还是比较麻烦的,代码也比较长。看了柳婼的博客才知道根本没有必要重建树。
1、因为是二叉搜索树,所以最近公共祖先的节点值一定在U和V之间。
2、因为前序遍历是按该节点、左子树、右子树顺序遍历的:
所以从前往后遍历前序数组pre,设节点为ans,第一个满足(ans>=U&&ans<=V)||(ans>=V&&ans<=U)的ans就是U和V的最近公共祖先。

解法2

#include <iostream>
#include <vector>
#include <cstdio>
#include <map>
#define MAX 10100
using namespace std;
map<int, bool> mp;
int M,N;
int pre[MAX];
int main()
{

    scanf("%d%d",&M,&N);
    for(int i=0;i<N;i++)
    {
        scanf("%d",&pre[i]);
        mp[pre[i]] = true;
    }
    for(int i=0;i<M;i++)
    {
        int U,V,ans;
        scanf("%d%d",&U,&V);
        for(int j=0;j<N;j++)
        {
            ans = pre[j];
            if((ans>=U&&ans<=V)||(ans>=V&&ans<=U))
                break;
        }
        if(!mp[U])
        {
            if(!mp[V])
                printf("ERROR: %d and %d are not found.\n",U,V);
            else printf("ERROR: %d is not found.\n",U);
        }
        else if(!mp[V])
            printf("ERROR: %d is not found.\n",V);
        else if(ans==U)
            printf("%d is an ancestor of %d.\n", ans, V);
        else if(ans==V)
            printf("%d is an ancestor of %d.\n",ans,U);
        else
            printf("LCA of %d and %d is %d.\n",U,V,ans);
    }
}


更多二叉树题解

PAT二叉树题目总结

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

猜你喜欢

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