题意
给定二叉树的先序和后序遍历,要求判断二叉树是否唯一,并输出任意一种的中序遍历。
思路
仿照先序+中序的思路建树,但是由于不能确定左右子树的位置,所以对左子树的长度进行枚举,如果有两种以上情况的长度都合适,说明不唯一,取其中一种继续下去即可。
Sample Input1:
7
1 2 3 4 6 7 5
2 6 7 4 5 3 1
Sample Output1:
Yes
2 1 6 4 7 3 5
Sample Input2:
4
1 2 3 4
2 4 3 1
Sample Output2:
No
2 1 3 4
#include "bits/stdc++.h"
using namespace std;
vector<int> pre,pos;
struct Node{
int v;
Node* l{nullptr};
Node* r{nullptr};
};
bool _unique = true;
bool ok(int preL,int preR,int posL,int posR){
return preL > preR || pre[preL] == pos[posR];
}
Node* build(int preL,int preR,int posL,int posR){
if (preL > preR || posL > posR) return nullptr;
Node* node = new Node{pre[preL]};
int numL = -1;
for (int len = 0; len <= preR - preL; ++len) {
if(ok(preL+1,preL+len,posL,posL+len-1)
&& ok(preL+len+1,preR,posL+len,posR-1)){
if (numL != -1) _unique = false;
numL = len;
}
}
if (numL != -1){
node->l = build(preL+1,preL+numL,posL,posL+numL-1);
node->r = build(preL+numL+1,preR,posL+numL,posR-1);
}
return node;
}
bool blank = false;
void inOrder(Node* p){
if (p == nullptr) return;
inOrder(p->l);
if (blank) printf(" %d",p->v);
else printf("%d",p->v), blank = true;
inOrder(p->r);
}
int main(){
freopen("input.txt","r",stdin);
int n; cin >> n; pre.resize(n),pos.resize(n);
for (int i = 0; i < n; ++i) scanf("%d",&pre[i]);
for (int i = 0; i < n; ++i) scanf("%d",&pos[i]);
Node* root = build(0,n-1,0,n-1);
if (_unique) printf("Yes\n");
else printf("No\n");
inOrder(root); printf("\n");
}