题目是:
【题目描述】
输入一棵二叉树的先序和中序遍历序列,输出其后序遍历序列。
【输入】
共两行,第一行一个字符串,表示树的先序遍历,第二行一个字符串,表示树的中序遍历。树的结点一律用小写字母表示。
【输出】
一行,表示树的后序遍历序列。
【输入样例】
abdec dbeac
【输出样例】
debca
额,真丢脸啊,这道题从11月7日卡在脑袋里卡到了现在(mmp硬是没有看题解);
不过老李讲的还是挺好的,打call;
本题利用了先序遍历的“先根”性质(每输出的一个值都是当先dfs时间戳的节点的值),且序列中的第一个元素一定是根节点;——性质1;
中序遍历则利用了“左左右右”(左边的是左儿子,右边是右儿子);——性质2;
两者相结合:
我们就可以用先序遍历的根节点,去找这个根节点在中序遍历的位置,那么利用性质2,去找它的左儿子和右儿子的区间分别在哪里,确定了左儿子和右儿子的区间后,这两个区间内一定又会有一个“当爸爸的父亲节点“,而这个区间里面的父亲节点,一定是先序遍历中当前节点向后的一个节点(性质1)相当于二分;
下面是代码(st是start的缩写,en是end的缩写)
1、数组(在遍历的时候就输出)
#include<bits/stdc++.h>
using namespace std;
string s1,s2;
void wans( int st1 , int en1 , int st2 , int en2 ){
if( st1 <= en1 ){
int root = s2.find ( s1[st1] , st2 );
wans ( st1+1 , st1+root-st2 , st2 , root-1 );
wans ( st1+root-st2+1 , en1 , root+1 , en2 );
cout<<s1[st1];
}
}
int main(){
cin>>s1;
cin>>s2;
wans(0 , s1.size()-1 , 0 , s2.size()-1 );
return 0;
}
2、建树,先建树后常规跑后序 dfs;
#include<bits/stdc++.h>
using namespace std;
typedef struct node;
typedef node *tree;
struct node{
char data;
tree l,r;
};
tree root;
string s1,s2;
void build( int st1 , int en1 , int st2 , int en2 , tree &bt ){
bt=new node;
bt->data = s1[st1];
if( st1 <= en1 ){
int x = s2.find( s1[st1] , st2 );
build( st1+1 , st1+x-st2 , st2 , x-1 , bt->l);
build( st1+x-st2+1 , en1 , x+1 , en2 , bt->r);
}
else
bt = NULL;
}
void visit( tree bt ){
if( bt ){
visit( bt->l );
visit( bt->r );
cout<<bt -> data;
}
}
int main(){
cin>>s1;
cin>>s2;
build( 0 , s1.size()-1 , 0 , s2.size()-1 , root );
visit(root);
return 0;
}
感觉lqx和hy同学学得很快,加油!