题目描述:
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(<=30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:7 1 2 3 4 5 6 7 4 1 3 2 6 5 7输出样例:
4 6 1 7 5 3 2
题目思路:
这道题目和L2-006.树的遍历很相似(具体思路点开链接查看),上一道题目是给出后序和中序,求出层次遍历。这道题目是给出先序和中序,求出镜面反转后的层次遍历。还是同样的,在递归函数添加一个参数index表示当前递归层的根节点在层次遍历中的坐标。既然是镜面,那么我们只要把递归左子树的坐标和递归右子树的坐标进行调换即可。也许有的人会问,只要先递归右子树,然后递归左子树不就可以了吗?答案是不可以。就算是交换了左右子树的递归顺序,之前的层次遍历坐标还是要交换 ,因为不管你先进行哪边子树的递归,在这个问题中是无所谓的,因为递归时候的index和先递归左右子树没有关系。而我们所熟知的通过先序遍历和中序遍历求后序遍历中,一定是先递归左子树,然后再递归右子树是因为后序遍历的顺序是,左+右+根节。因此,我们先左递归后,使得在递归栈中先弹出的是左结点,然后是右结点,之后返回上一层递归进行同样操作。
题目代码:
#include<cstdio>
#include<cmath>
#include<iostream>
#define MAXN 10000
using namespace std;
int s1[MAXN], s2[MAXN], s3[MAXN], n;
void f(int p1, int p2 ,int q1, int q2, int index)
{
//stop
if(p1>p2 || q1>q2) return ;
int i = p1;
while(s1[i] != s2[q1]) i++;
s3[index] = s2[q1];
//left
f(p1, i-1, q1+1, q1+i-p1, 2*index+2);
//right
f(i+1, p2, q1+i-p1+1 ,q2, 2*index+1);
}
int main() {
cin>>n;
for(int i=0; i<n; i++) cin>>s1[i];
for(int i=0; i<n; i++) cin>>s2[i];
f(0, n-1, 0, n-1 ,0);
int cnt = 0;
for(int i=0 ;i<MAXN ;i++){
if(s3[i]){
if(cnt)cout<<" ";
cout<<s3[i];
cnt++;
}
}
return 0;
}