题目大意:给出二叉树的中序遍历和后序遍历,求一个叶子结点,它到根的距离最短,若有多个解叶子权值应该最小。
递归遍历,每次找到当次递归的根然后递归左子树和右子树,后序遍历的最后一个结点就是根,在递归过程中记录根到当前结点的距离,这样可以在递归到达叶子时就能得到那个叶子结点到根的距离。这样可以不用恢复二叉树。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int a[10010];
int b[10010];
int c[10010];
char e[100010];
int dis[10010];
int isleaf[10010];
int sum;
void dfs(int u,int v,int p);
int main(void)
{
int i,topa,topb,sump,lo,min,minans;
while(gets(e)!=NULL)
{
topa=topb=sum=0;
lo=strlen(e);
i=0;
while(i<lo)
{
if((e[i]>='0')&&(e[i]<='9'))
{
sump=0;
while((e[i]>='0')&&(e[i]<='9'))
{
sump=sump*10+e[i]-'0';
i++;
}
a[++topa]=sump;
}
else
{
i++;
}
}
gets(e);
lo=strlen(e);
i=0;
while(i<lo)
{
if((e[i]>='0')&&(e[i]<='9'))
{
sump=0;
while((e[i]>='0')&&(e[i]<='9'))
{
sump=sump*10+e[i]-'0';
i++;
}
b[++topb]=sump;
}
else
{
i++;
}
}
for(i=1;i<=topa;i++)
{
c[a[i]]=i;
isleaf[b[i]]=dis[b[i]]=0;
}
dfs(1,1,topa);
min=(1<<30);
minans=0;
for(i=1;i<=topa;i++)
{
if(isleaf[a[i]]==1)
{
if((dis[a[i]]<min)||((dis[a[i]]==min)&&(a[i]<minans)))
{
min=dis[a[i]];
minans=a[i];
}
}
}
printf("%d\n",minans);
}
return 0;
}
void dfs(int u,int v,int p)
{
int j,uu,vv;
if(p==1)
{
isleaf[a[u]]=1;
dis[a[u]]=sum+a[u];
}
else
{
sum+=b[v+p-1];
j=c[b[v+p-1]];
uu=u+p-1-j;
vv=p-uu-1;
if(uu>0)
{
dfs(j+1,v+p-1-uu,uu);
}
if(vv>0)
{
dfs(u,v,vv);
}
sum-=b[v+p-1];
}
}