PTA 甲级真题 1151 LCA in a Binary Tree

题目链接

题目:求解最近公共祖先

思路:分别从两个结点向上遍历,最先遍历两次的就是LCA

涉及:根据中序和先序序列确定二叉树,我使用了map来映射结点value和下标的关系

易错点:

1.节点不存在,要输出不存在的结点,并结束

2.若其中一个结点是另一个结点的情况 ;和两个结点互不为祖先的情况,一定有共同祖先,因为有根嘛。

#include<iostream>
#include<string.h>
#include<map>
#define MAXN 10005
using namespace std;


map<int,int> value_index;
int vis[MAXN];
struct Node{
    int value;
    int left=-1,right=-1,parent=-1;//下标
};
struct Node node[MAXN];
int inOrder[MAXN],preOrder[MAXN];
int ind=0;

int createTree(int left_in,int right_in,int left_pre,int right_pre){//返回下标
    if(left_in>right_in)return -1;
    int root=preOrder[left_pre];
    int root_pos_in=left_in;//中序序列根的下标
    while(inOrder[root_pos_in]!=root){
        root_pos_in++;
    }
    int i = ind++;
    value_index[root]=i;//
    node[i].value=root;
    node[i].left=createTree(left_in,root_pos_in-1, left_pre+1,left_pre+root_pos_in-left_in-1);
    if(node[i].left!=-1){
        node[node[i].left].parent=i;
    }
    node[i].right=createTree(root_pos_in+1,right_in, left_pre+root_pos_in-left_in+1, right_pre);
    if(node[i].right!=-1){
        node[node[i].right].parent=i;
    }
    return i;
}


int getLCA(int a,int b){//传入的是结点值,返回下标
    memset(vis,0,sizeof(vis));
    a=value_index[a];//下标 
    b=value_index[b];
    while(a!=-1){
        vis[a]++;
        a=node[a].parent;
    }
    while(b!=-1){
    	vis[b]++;
    	if(vis[b]>1)return b;
        b=node[b].parent;
    }
    return -1;
}

int main(){
    int m,n;//m测试的节点对,n结点个数
    cin>>m>>n;
    for(int i=0;i<n;i++){
        cin>>inOrder[i];
    }
    for(int i=0;i<n;i++){
        cin>>preOrder[i];
    }
    //确定二叉树
    int root_i=createTree(0,n-1,0,n-1);
    //求解最近共同祖先 结点a,b。我的思路是:分别向上遍历,如果有那个结点最先被遍历两次就是最近共同祖先
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        
        if(value_index.count(a)==0&&value_index.count(b)==0){
            printf("ERROR: %d and %d are not found.\n",a,b);
            continue;
        }
        else if(value_index.count(a)==0){
            printf("ERROR: %d is not found.\n",a);continue;
        }
        else if(value_index.count(b)==0){
            printf("ERROR: %d is not found.\n",b);continue;
        }
        int c=getLCA(a,b);
        c=node[c].value;
        if(vis[value_index[a]]>1){
            printf("%d is an ancestor of %d.\n",a,b);
        }
        else if(vis[value_index[b]]>1){
            printf("%d is an ancestor of %d.\n",b,a);
        }
        else {
//        	printf("%d %d %d\n",vis[value_index[a]],vis[value_index[b]],vis[value_index[c]]);
            printf("LCA of %d and %d is %d.\n",a,b,c);
        }
    }
    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值