欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PAT甲级 1151 LCA in a Binary Tree (30分) 最近公共祖先

程序员文章站 2022-07-14 15:18:59
...

PAT甲级 1151 LCA in a Binary Tree (30分) 最近公共祖先
PAT甲级 1151 LCA in a Binary Tree (30分) 最近公共祖先
PAT甲级 1151 LCA in a Binary Tree (30分) 最近公共祖先

题目大意:

给出中序序列和先序序列,再给出两个点,求这两个点的最近公共祖先

不建树的做法:

已知某个树的根结点,若a和b在根结点的左边,则a和b的最近公共祖先在当前子树根结点的左子树寻找,如果a和b在当前子树根结点的两边,在当前子树的根结点就是a和b的最近公共祖先,如果a和b在当前子树根结点的右边,则a和b的最近公共祖先就在当前子树的右子树寻找。

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<stack>
#include<map>
#define MAX 10020
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

map<int,int> pos;//记录中序中的节点的位置
int in[MAX],pre[MAX];//中序和前序
int n,m,a,b;

void lca(int inl,int inr,int preroot,int a,int b) {//l和r为中序中的位置
    if(inl>inr) return;
    int inroot=pos[pre[preroot]];//inroot为中序中根节点的位置
    int ain=pos[a],bin=pos[b];
    if(ain<inroot&&bin<inroot){//若a和b都在左子树中
        lca(inl,inroot-1,preroot+1,a,b);
    }else if((ain<inroot&&bin>inroot)||(ain>inroot&&bin<inroot)){//若a和b一个在左子树,一个在右子树
        printf("LCA of %d and %d is %d.\n",a,b,in[inroot]);
    }else if (ain>inroot&&bin>inroot){//若a和b都在右子树中
        lca(inroot+1,inr,preroot+1+(inroot-inl),a,b);
    }else if(ain==inroot){
            printf("%d is an ancestor of %d.\n",a,b);
    }else if (bin==inroot){
            printf("%d is an ancestor of %d.\n",b,a);
    }
}

int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&in[i]);
        pos[in[i]]=i;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&pre[i]);
    }
    for(int i=0;i<m;i++){
        scanf("%d%d",&a,&b);
        if(pos[a]==0&&pos[b]==0){
            printf("ERROR: %d and %d are not found.\n",a,b);
        }else if(pos[a]==0||pos[b]==0){
            printf("ERROR: %d is not found.\n",pos[a]==0?a:b);
        }else{
            lca(1,n,1,a,b);
        }
    }
    return 0;
}

建树的做法:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<stack>
#include<map>
#define MAX 10020
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

struct node{
    int key;
    node* left;
    node *right;
};

map<int,int> mp;//记录中序中的节点的位置
int in[MAX],pre[MAX];//中序和前序
int n,m,a,b;

node* build_tree(int r,int start,int ends){
    if(start>ends){
        return NULL;
    }
    int i=start;
    while(i<ends&&in[i]!=pre[r]){
        i++;
    }
    node* root=(node *)malloc(sizeof(node));
    root->key=pre[r];
    root->left=build_tree(r+1,start,i-1);//遍历左子树
    root->right=build_tree(r+1+i-start,i+1,ends);//遍历右子树
    return root;
}

node* lca(node* root,int a,int b){//lca算法
    if(root==NULL||root->key==a||root->key==b) return root;
    node* L=lca(root->left,a,b);
    node* R=lca(root->right,a,b);
    if(L==NULL) return R;
    if(R==NULL) return L;
    return root;
}

int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&in[i]);
        mp[in[i]]=1;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&pre[i]);
    }
    node *root=build_tree(1,1,n);//建立二叉树
    for(int i=0;i<m;i++){
        scanf("%d%d",&a,&b);
        if(mp[a]==0&&mp[b]==0){
            printf("ERROR: %d and %d are not found.\n",a,b);
        }else if(mp[a]==0){
            printf("ERROR: %d is not found.\n",a);
        }else if(mp[b]==0){
            printf("ERROR: %d is not found.\n",b);
        }else{
            node *res=lca(root,a,b);
            if(res->key==a){
                printf("%d is an ancestor of %d.\n",a,b);
            }else if(res->key==b){
                printf("%d is an ancestor of %d.\n",b,a);
            }else{
                printf("LCA of %d and %d is %d.\n",a,b,res->key);
            }
        }
    }
    return 0;
}