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 }


浙公网安备 33010602011771号