【机试备考】Day16-二叉树 | 前序中序求后序

题目

BUPT 2017 计算机 ProblemC
输入二叉树的前序遍历和中序遍历结果,输入二叉树的后序遍历结果。

输入描述

第一行为二叉树先序遍历结果。
第二行为二叉树中序遍历结果。

输出描述

二叉树后序遍历结果

示例

输入

426315
623415

输出

632514

题解

依稀记得王道上有原题,06年清华机试的原题

Leetcode105有一道根据前序和中序建树的题,和这题基本上一样,可以看一眼力扣给出的题解,配有视频讲解,讲的挺好的

思路

  1. 建树:根据前序序列找到节点preLeft,在中序序列找到根节点序号pIndex,此时如图,可确定左右子树序号范围,即找到了根和对应左右子树
  2. 对于1中的根节点的左右子树递归继续执行步骤1,直到preLeft>preRight,建立二叉树完成
    在这里插入图片描述
  3. 后序遍历输出二叉树

代码

#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

猜你喜欢

转载自blog.csdn.net/qq_43417265/article/details/113585168