1119 Pre- and Post-order Traversals (先序+后序 =(非唯一) 二叉树)

题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805353470869504

题目大意:

给出一棵树的结点个数n,以及它的前序遍历和后序遍历,输出它的中序遍历,如果中序遍历不唯一就输出No,且输出其中一个中序即可,如果中序遍历唯一就输出Yes,并输出它的中序。

分析:

判断依据,如果一棵二叉树的某个结点的左子树或者右子树为空,那么无法根据其先序和后序唯一确定这棵二叉树。

如何根据当前的先序和后序找出根结点呢?

首先,前序的第一个和后序的倒数第一个是相等的,这个结点就是根结点。

然后,后序遍历的倒数第二个结点为右子树的根结点(假设右子树始终存在),并用这个根结点找到其在先序中的位置,如果根结点的左边没有一个结点,那么说明当前根结点没有左子树,即无法唯一确定该二叉树,然后通过根结点划分左、右子树先序序列和左、右子树后序序列,递归处理。

 1 #include<iostream>
 2 #include<vector>
 3 using namespace std;
 4 
 5 vector<int> pre,in,post;
 6 
 7 bool unique = true;
 8 void create(int preL,int preR,int postL,int postR) {
 9     if(preL == preR) { //叶子结点
10         in.push_back(pre[preL]);
11         return ;
12     }
13     //查找下一个根结点在先序序列中的位置
14     int k = preL+1,leftNum;
15     while(k <= preR && pre[k] != post[postR-1]) k++;
16     leftNum = k-preL-1;
17     if(k - preL > 1)//如果下一个根结点的左子树存在
18         create(preL+1,preL+leftNum,postL,postL+leftNum-1);
19     else //左子树不存在,二叉树不唯一 
20         unique = false;
21     in.push_back(pre[preL]);
22     create(preL+leftNum+1,preR,postL+leftNum,postR-1);
23 }
24 
25 int main() {
26     int n;
27     cin>>n;
28     pre.resize(n);
29     post.resize(n);
30     for(int i = 0; i < n; ++i) cin>>pre[i];
31     for(int i = 0; i < n; ++i) cin>>post[i];
32     create(0,n-1,0,n-1);
33     if(unique) printf("Yes\n");
34     else printf("No\n");
35     for(int i = 0; i < in.size(); ++i) {
36         if(i > 0) printf(" ");
37         printf("%d",in[i]);
38     }
39     printf("\n");
40     return 0;
41 }

 

posted @ 2020-03-24 09:51  tangq123  阅读(182)  评论(0)    收藏  举报