下午刷了一个二叉搜索树中找最小公共祖先的问题,所以又迫不及待地打开了这道类似的题。本题是给出二叉树的前序遍历和中序遍历,然后要求你求出任意两个节点的最小公共祖先。
尼玛啊,做了这道题才发现前边那个二叉搜索树的LCA问题是真的水,二叉树不具有像二叉搜索树那样左右节点之间的大小关系,所以说我认为本题稍微难于上一道题。
弱鸡同样借助于大神的题解pdf.jpg
解题思想:从根开始向下遍历,如果满足u和v分别在当前的节点的两侧的话,那么这个点就是要找的点,否则分情况向左找和向右找
难受的是,测试点四超时了,只拿了26分,找了一个多小时也没找出来
如果有大神发现可以修改的地方,请帮我指出,拜托了~
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+100;
map<int,int>mp;
map<int,int>MP;
int posu,posv;
int n,m,u,v,pre[maxn],in[maxn],ans,pos[maxn];
void find(int root,int start,int end) {
if(start>end) return;
int i=start;
while(pre[root]!=in[i]&&i<end) i++;
if(i<=posu&&i>=posv||i<=posv&&i>=posu) {
ans=in[i];
return;
} else if(i<posu&&i<posv) find(root+1+i-start,i+1,end);//右子树里去找
else if(i>posu&&i>posv) find(root+1,start,i-1);//左子树里去找
}
int main() {
cin>>m>>n;
for(int i=0; i<n; i++) {
scanf("%d",&in[i]);
MP[in[i]]=i+1;
mp[in[i]]=1;
}
for(int i=0; i<n; i++) {
scanf("%d",&pre[i]);
}
while(m--) {
posu=-1;
posv=-1;
scanf("%d%d",&u,&v);
if(MP[u]&&MP[v]){
posu=MP[u]-1;
posv=MP[v]-1;
find(0,0,n);
}
if(!mp[u]&&!mp[v]) printf("ERROR: %d and %d are not found.\n",u,v);
else if(!mp[u]||!mp[v]) printf("ERROR: %d is not found.\n",!mp[u]?u:v);
else if(ans==u||ans==v) printf("%d is an ancestor of %d.\n",ans==u?u:v,ans==u?v:u);
else printf("LCA of %d and %d is %d.\n",u,v,ans);
}
return 0;
}
还有,近期需要做一下二叉树中序前序转后序和中序后序转前序的归纳~