题目: 给出一棵二叉树的中序遍历和后序遍历, 求所在路径权值最小的叶子节点, 若权值相等取编号小的叶子。并且每个节点的权值都不同。
分析: 只要给出先序、中序、后续其中两个,,一棵二叉树就唯一确定了。 只需递归建树后就可以DFS求解了。 原问题就可以划分为两个简单的问题了。
所谓的先后序是指 根节点的先后顺序,儿子间的顺序总是左二子先于右儿子。
如: 中序: d b e a f c g
后序: d e b f g c a
由后序可以确定根节点为 a,结合中序可知 d b e都是左儿子的节点, f c g都是右儿子的节点。
由此可以得到一个递推建树的方法。
求最小权值的过程是标准的DFS.
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=10010<<1;
int a[MAXN],b[MAXN],Lson[MAXN],Rson[MAXN],root;
int N,MinVal,Best;
int AD(int *s,int c){
for(int p=0;p<N;p++){
if(s[p]==c) return p;
}
return -1;
}
void Build(int n,int *a,int *b)
{
int fa=b[n-1];
if(n<=1){
Lson[fa]=Rson[fa]=0; return;
}
int m=AD(a,fa);
Lson[fa]= m==0?0:b[m-1] , Rson[fa]= m==n-1?0:b[n-2];
if(Lson[fa]) Build(m,a,b);
if(Rson[fa]) Build(n-m-1,a+m+1,b+m);
}
void DFS(int u,int val)
{
if(!Rson[u] && !Lson[u]){
if(val+u<MinVal){
MinVal=val+u,Best=u;
}else if(val+u==MinVal){
Best=u<Best?u:Best;
}
return ;
}
if(Lson[u]) DFS(Lson[u],val+u);
if(Rson[u]) DFS(Rson[u],val+u);
}
int main()
{
while(scanf("%d",&a[0])!=EOF){
N=1;
char c=getchar();
while(c != '\n') scanf("%d",&a[N++]),c=getchar();
for(int i=0;i<N;i++) scanf("%d",&b[i]);
root=b[N-1];
Build(N,a,b);
Best=MinVal=(int)1e9;
DFS(root,0);
printf("%d\n",Best);
}
return 0;
}