1151 LCA in a Binary Tree (30 分)

LZ做题太少,一开始只想到建树、然后分别找到两个元素所在的分支序列、然后找到第一个公共元素这种方法,提交之后得到22分,最后两个测试点超时;后来参考大佬https://blog.csdn.net/qq_41317652/article/details/82557975的方法,原来lca只需要一次遍历就ok了,不需要找两个序列,下面附上我的22分代码(第2段代码)和AC代码(第1段代码);

#include<bits/stdc++.h>
using namespace std;
const int MAXN=10003;
struct Node{
	int data;
	Node* left;
	Node* right;
};
vector<int> in,pre;
int fa[MAXN];
int m,n;
Node* build(int inl,int inr,int prel,int prer){
	if(prel>prer) return NULL;
	Node* root=new Node;
	root->data=pre[prel];
	root->left=root->right=NULL;
	int k;
	for(int i=inl;i<=inr;i++){
		if(in[i]==pre[prel]){
			k=i;break;
		}
	}
	int numleft=k-inl;
	root->left=build(inl,k-1,prel+1,prel+numleft);
	root->right=build(k+1,inr,prel+numleft+1,prer);
	return root;
}
bool findnode(int x){
	for(int i=0;i<n;i++){
		if(pre[i]==x) return true;
	}
	return false;
}
Node* lca(Node* root,int a,int b){
	if(root==NULL) return NULL;
	if(root->data==a||root->data==b) return root;
	Node* l=lca(root->left,a,b);
	Node* r=lca(root->right,a,b);
	if(l&&r) return root;
	if(!l&&r) return r;
	if(l&&!r) return l;
} 
int main()
{
	freopen("in.txt","r",stdin);
	cin>>m>>n;
	for(int i=0;i<=10002;i++) fa[i]=i;
	in.resize(n);pre.resize(n);
	for(int i=0;i<n;i++){
		cin>>in[i];
	}
	for(int i=0;i<n;i++){
		cin>>pre[i];
	}
	Node* root=build(0,n-1,0,n-1);
	for(int i=0;i<m;i++){
		int a,b;cin>>a>>b;
		int flaga=0,flagb=0;
		if(!findnode(a)) flaga=1;
		if(!findnode(b)) flagb=1;
		if(flaga==1&&flagb==1) {printf("ERROR: %d and %d are not found.\n", a, b);continue;}
		if(flaga==1&&flagb==0) {printf("ERROR: %d is not found.\n", a);continue;}
		if(flaga==0&&flagb==1) {printf("ERROR: %d is not found.\n", b);continue;}
		Node* si=lca(root,a,b);
		if(si->data==a) {
			cout<<a<<" is an ancestor of "<<b<<"."<<endl;continue;
		}
		if(si->data==b) {
			cout<<b<<" is an ancestor of "<<a<<"."<<endl;continue;
		}
		if(si->data!=a&&si->data!=b) {
			cout<<"LCA of "<<a<<" and "<<b<<" is "<<si->data<<"."<<endl;continue;
		}
	}
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
//const int MAXN=10003;//会出现段错误 
struct Node{
	int data;
	Node* left;
	Node* right;
};
vector<int> in,pre;
//int fa[MAXN];
map<int,int> fa;//改成map避免段错误,即数组越界 
int m,n;
Node* build(int inl,int inr,int prel,int prer){
	if(prel>prer) return NULL;
	Node* root=new Node;
	root->data=pre[prel];
	root->left=root->right=NULL;
	int k;
	for(int i=inl;i<=inr;i++){
		if(in[i]==pre[prel]){
			k=i;break;
		}
	}
	int numleft=k-inl;
	root->left=build(inl,k-1,prel+1,prel+numleft);
	root->right=build(k+1,inr,prel+numleft+1,prer);
	return root;
}
void pretra(Node* root){
	if(root==NULL) return;
	if(root->left!=NULL) fa[root->left->data]=root->data;
	if(root->right!=NULL) fa[root->right->data]=root->data;
	pretra(root->left);
	pretra(root->right);
}
bool findnode(int x){
	for(int i=0;i<n;i++){
		if(pre[i]==x) return true;
	}
	return false;
}
int main()
{
	freopen("in.txt","r",stdin);
	cin>>m>>n;
	//for(int i=0;i<=10002;i++) fa[i]=i;
	in.resize(n);pre.resize(n);
	for(int i=0;i<n;i++){
		cin>>in[i];
	}
	for(int i=0;i<n;i++){
		cin>>pre[i];
		fa[pre[i]]=pre[i];
	}
	Node* root=build(0,n-1,0,n-1);
	pretra(root);
	for(int i=0;i<m;i++){
		int a,b;cin>>a>>b;
		int flaga=0,flagb=0;
		if(!findnode(a)) flaga=1;
		if(!findnode(b)) flagb=1;
		if(flaga==1&&flagb==1) {cout<<"ERROR: "<<a<<" and "<<b<<" are not found."<<endl;continue;}
		if(flaga==1&&flagb==0) {cout<<"ERROR: "<<a<<" is not found."<<endl;continue;}
		if(flaga==0&&flagb==1) {cout<<"ERROR: "<<b<<" is not found."<<endl;continue;}
		vector<int> p1,p2;
		int xa=a,xb=b;
		while(fa[xa]!=xa){
			p1.push_back(xa);
			xa=fa[xa];
		}
		p1.push_back(xa);
		while(fa[xb]!=xb){
			p2.push_back(xb);
			xb=fa[xb];
		}
		p2.push_back(xb);
		map<int,int> mp;int si;
		for(int k=0;k<p1.size();k++){
			mp[p1[k]]=1;
		} 
		for(int k=0;k<p2.size();k++){
			if(mp[p2[k]]==1) {
				si=p2[k];break;
			}
		}
		if(si==a) {
			cout<<a<<" is an ancestor of "<<b<<"."<<endl;continue;
		}
		if(si==b) {
			cout<<b<<" is an ancestor of "<<a<<"."<<endl;continue;
		}
		if(si!=a&&si!=b) {
			cout<<"LCA of "<<a<<" and "<<b<<" is "<<si<<"."<<endl;continue;
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值