给出一个二叉排序树的前序序列,再任意给两个点,求两个点的最小祖先
一开始:
按照套路,先建树,然后遍历树的思想。
建树采用输入一个点然后插入树的方法。
遍历树用了map数组。
此时有三个点运行超时,cin、cout改为scanf和printf都未能解决问题。
于是开始从库函数下手。
后来发现,map数组改为使用int数组,运行变快了
原来用的遍历方法是用两个vector数组保存树根到两个点的路径,然后逐个比较得到两条路径最后一个相等的点。
后来:
采用了新的代码,从叶子开始后序递归,遍可以得到最低公共祖先的结点,这个算法真的开了我的眼,以至于我到现在还没看通透。。。
Node* findnode(Node* r,int a,int b)
{
if(r==NULL)
return NULL;
if(a==r->key||b==r->key)
return r;
Node* left=findnode(r->left,a,b);
Node* right=findnode(r->right,a,b);
if(left!=NULL&&right!=NULL)
return r;
return left==NULL?right:left;
}
同时,给出一个二叉排序树的前序序列,其从小到大重新排序后,即为中序序列。查了别人的代码后,用了先一次性输入存储前序和中序序列,然后再一次性建树的方法,运行超时解决。
再后来:
发现一个神仙的代码,根本就没有建树,运行时间大幅减少。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=10010;
int pre[maxn];
int k,n;
int main(){
scanf("%d%d",&k,&n);
for(int i=0;i<n;i++){
scanf("%d",&pre[i]);
}
int u,v;
for(int q=0;q<k;q++){
bool findU=false,findV=false;
scanf("%d%d",&u,&v);
int posU,posV;
for(int i=0;i<n;i++){
if(pre[i]==u){
findU=true;
posU=i;
}
if(pre[i]==v){
findV=true;
posV=i;
}
}
if(findU==false&&findV==false){
printf("ERROR: %d and %d are not found.\n",u,v);
continue;
}
if(findU==false){
printf("ERROR: %d is not found.\n",u);
continue;
}
if(findV==false){
printf("ERROR: %d is not found.\n",v);
continue;
}
bool isSwap=false;//标记u,v是否交换过
if(u>v){
swap(u,v);
swap(posU,posV);
isSwap=true;
}
int num=-1;
for(int i=0;i<n;i++){
if(pre[i]>u&&pre[i]<=v&&i<posV){//i欲成为v的祖先,在pre序列中,i必须在v之前
num=i;
break;
}
}
if(num!=-1){
if(isSwap){//u,v交换过
swap(u,v);
}
printf("LCA of %d and %d is %d.\n",u,v,pre[num]);
}
else{
if(posU>posV){
swap(u,v);
}
printf("%d is an ancestor of %d.\n",u,v);
}
}
return 0;
}
---------------------
作者:harvien9
来源:优快云
原文:https://blog.youkuaiyun.com/qq_38705851/article/details/82387888
版权声明:本文为博主原创文章,转载请附上博文链接!