题意:给出先序,后序,问二叉树是否唯一,输出中序。
思路:根据先序确定当前树的根,若二叉树唯一,则可以根据先序把后序划分成两个部分,第一部分为右子树,第二部分为左子树。若不唯一,怎只能划分成一个部分,作为左子树或右子树都行。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAX_N = 35;
int pre[MAX_N], post[MAX_N];
int n;
bool flag;
int lc[MAX_N], rc[MAX_N];
int build(int prel, int prer, int postl, int postr) {
if (prel >= prer) return -1;
if (prer-prel == 1) return prel;
int p = -1;
for (int i = postl; i < postr-1; i++) {
if (pre[prel+1] == post[i]) {
p = i; break;
}
}
if ((p+1-postl) == 1 && (postr-1-p-1) == 0) flag = false;
lc[prel] = build(prel+1, prel+p-postl+2, postl, p+1);
rc[prel] = build(prel+p-postl+2, prer, p+1, postr-1);
return prel;
}
int in[MAX_N];
int len;
void inorder(int r) {
if (r == -1) return ;
inorder(lc[r]);
in[len++] = r;
inorder(rc[r]);
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &pre[i]);
for (int i = 0; i < n; i++) scanf("%d", &post[i]);
memset(lc, -1, sizeof(lc));
memset(rc, -1, sizeof(rc));
flag = true;
int r = build(0, n, 0, n);
if (flag) printf("Yes\n");
else printf("No\n");
len = 0;
inorder(r);
for (int i = 0; i < len; i++) {
if (i > 0) printf(" ");
printf("%d", pre[in[i]]);
}
printf("\n");
return 0;
}