Sample Input 1:
7
1 2 3 4 6 7 5
2 6 7 4 5 3 1
Sample Output 1:
Yes
2 1 6 4 7 3 5
Sample Input 2:
4
1 2 3 4
2 4 3 1
Sample Output 2:
No
2 1 3 4
题解:
给出树的先序和后序遍历,
这里先把树结构给出:
可以发现在先序遍历中节点i
的后一个节点必定是在其子树中,比如1
的后一个节点2
。同样,在后序遍历中节点i
的前一个节点必定是在其子树中,比如1
的前一个节点3
。
可以利用该特点将大树化小树,递归遍历。
1.定义数据,先序数组pre[]
,后序数组post[]
,中序vector<int> inorder
,先序中根节点下标root
;后序中左边起始下标left
,右边终止下标right
;树结构是否唯一标志unique=false
2.root=0
,left=0
,right=6
,
pre[root+1]
是root节点下子树的根节点,找到pre[root+1]
在后序中的位置i
,如果发现i == right-1
,就说明无法确定i
节点是在root
的左子树还是右子树,构建的树就不唯一,使unique = true
,
进行左子树递归调用root = root+1
,left=left
,right=i
3.root=1
,left=0
,right=0
,
发现 right==left
,将post[left]
加入inorder
,inorder=[2]
,回调
4.将pre[root]
加入inorder
,inorder=[2,1]
,遍历右子树,令root = root + 1 + (i - left + 1)
,left = i + 1
,right = right - 1
,其中(i - left + 1)
表示的是root左子树的所有结点个数,在先序中跳过这些结点才到达右子树的根结点
5.root = 2
,left = 1
,right = 5
发现left != right
,递归调用左子树,root = root+1
,left=left
,right=i
6.root = 3
,left = 1
,right = 3
6.再次递归调用左子树,root = root+1
,left=left
,right=i
7.root = 4
,left = 1
,right = 1
发现 right==left
,将post[left]
加入inorder
,inorder=[2,1,3,6]
,回到6,将将pre[root]
加入inorder
,inorder=[2,1,3,6,4]
,遍历右子树
8.root = 5
,left = 2
,right = 2
发现 right==left
,将post[left]
加入inorder
,inorder=[2,1,3,6,4,7]
,回到5,将将pre[root]
加入inorder
,inorder=[2,1,3,6,4,7,3]
,遍历右子树
8.root = 6
,left = 4
,right = 4
发现 right==left
,将post[left]
加入inorder
,inorder=[2,1,3,6,4,7,5]
,遍历结束
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int pre[30],post[30];
vector<int> inorder;
int n;
bool unique = false;
void inord(int root,int left,int right){
if(left >= right){
if(left == right){
inorder.push_back(post[left]);
}
return;
}
int i = left;
while(i <= right -1 && post[i] != pre[root+1]) i++;
if(i == right -1) unique = true;
inord(root+1,left,i);
inorder.push_back(pre[root]);
inord(root + 1 + (i - left +1),i+1,right - 1);
}
int main(){
cin >> n;
for(int i=0;i<n;i++){
scanf_s("%d",&pre[i]);
}
for(int i=0;i<n;i++){
scanf_s("%d",&post[i]);
}
inord(0,0,n-1);
if(unique){
cout << "No"<< endl;
}
else{
cout << "Yes"<< endl;
}
for(int i=0;i<inorder.size();i++){
cout << inorder[i];
if(i != inorder.size() - 1){
cout << " ";
}
}
printf("\n");
system("pause");
return 0;
}