题目
BUPT 2017 计算机 ProblemC
输入二叉树的前序遍历和中序遍历结果,输入二叉树的后序遍历结果。
输入描述
第一行为二叉树先序遍历结果。
第二行为二叉树中序遍历结果。
输出描述
二叉树后序遍历结果
示例
输入
426315
623415
输出
632514
题解
依稀记得王道上有原题,06年清华机试的原题
Leetcode105有一道根据前序和中序建树的题,和这题基本上一样,可以看一眼力扣给出的题解,配有视频讲解,讲的挺好的
思路
- 建树:根据前序序列找到根节点preLeft,在中序序列找到根节点序号pIndex,此时如图,可确定左右子树序号范围,即找到了根和对应左右子树
- 对于1中的根节点的左右子树递归继续执行步骤1,直到preLeft>preRight,建立二叉树完成
- 后序遍历输出二叉树
代码
#include<iostream>
#include<string>
using namespace std;
typedef struct node
{
struct node *left;
struct node *right;
int val;
node(int v)
{
left=NULL;
right=NULL;
val=v;
}
}node,*tree;
//后序遍历
void PostOrder(tree T)
{
if(T)
{
PostOrder(T->left);
PostOrder(T->right);
cout<<T->val;
}
}
//建树
tree build(string pre,int preLeft,int preRight,string mid,int inLeft,int inRight)
{
//递归结束
if(preLeft>preRight)
return NULL;
//根序号即前序序列首个元素
int i,rootIndex=pre[preLeft]-'0';
//建根
tree root=new node(rootIndex);
//找出根节点在中序遍历序列中的位置i
for(i=inLeft;i<=inRight;i++)
{
if(mid[i]-'0'==rootIndex)
break;
}
//从前序和中序序列中找出左子树的部分,序号如上图,建立左子树
root->left=build(pre,preLeft+1,i-inLeft+preLeft,mid,inLeft,i-1);
//右子树
root->right=build(pre,i-inLeft+preLeft+1,preRight,mid,i+1,inRight);
return root;
}
int main()
{
string post,pre,mid;
cin>>pre>>mid;
tree T=build(pre,0,pre.length()-1,mid,0,mid.length()-1);
PostOrder(T);
}
改进
由于每次确定根节点序号再到中序序列中遍历查找,导致时间复杂度较高,因此采用建立哈希表,存储中序序列元素和其位置的对应关系,每次去哈希表中查找的方法改进,以空间换时间
#include<iostream>
#include<string>
using namespace std;
int index[100];
typedef struct node
{
struct node *left;
struct node *right;
int val;
node(int v)
{
left=NULL;
right=NULL;
val=v;
}
}node,*tree;
//后序遍历
void PostOrder(tree T)
{
if(T)
{
PostOrder(T->left);
PostOrder(T->right);
cout<<T->val;
}
}
//建树
tree build(string pre,int preLeft,int preRight,string mid,int inLeft,int inRight)
{
//递归结束
if(preLeft>preRight)
return NULL;
//根序号,即前序序列首个元素
int rootIndex=pre[preLeft]-'0';
//改进:直接查哈希表找到根节点在中序的位置
int i=index[rootIndex];
//建根
tree root=new node(rootIndex);
//从前序和中序序列中找出左子树的部分,序号如上图,建立左子树
root->left=build(pre,preLeft+1,i-inLeft+preLeft,mid,inLeft,i-1);
//右子树
root->right=build(pre,i-inLeft+preLeft+1,preRight,mid,i+1,inRight);
return root;
}
int main()
{
string post,pre,mid;
cin>>pre>>mid;
//建立哈希表
for(int i=0;i<mid.length();i++)
{
index[mid[i]-'0']=i;
}
tree T=build(pre,0,pre.length()-1,mid,0,mid.length()-1);
PostOrder(T);
}
时间复杂度O(n)
P.S 这几年的题真是越来越难了啊,这种难度只能保2争3