题目分析
我们接着上面的分析进一步讲解
1 2 3 4 6 7 5
2 6 7 4 5 3 1
虽然避免不了先序第一个仍然等于后序倒数第一个
但是,先序的第二个结点值2和后序的倒数第二个结点值3是不同的,这将导致2只能是左儿子,3只能是右儿子
且3一定是右子树的根节点,在前序遍历中找到3,之前的部分就一定是左子树节点
按照这个思路划分左右子树即可
如果先序的第二个结点值和后序的倒数第二个结点值相同
那么剩下的所有节点都属于同一个子树,且不能区分出到底是左子树还是右子树,即这棵树不唯一
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int N = 40;
int n, cnt = 0;
int pre[N], post[N], in[N];
int flag = 1;
void dfs(int pre1, int pre2, int post1, int post2)
{
if (pre1 == pre2) {
in[++cnt] = pre[pre1];
return;
}
if (pre[pre1] == post[post2]) {
int i = pre1 + 1;
while (i <= pre2 && pre[i] != post[post2 - 1]) i++;
if (i - pre1 > 1)
dfs(pre1 + 1, i - 1, post1, post1 + i - 1 - pre1 - 1);
else flag = 0;
in[++cnt] = post[post2];
dfs(i, pre2, post1 + i - 1 - pre1, post2 - 1);
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &pre[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &post[i]);
dfs(1, n, 1, n);
if (flag) printf("Yes\n");
else printf("No\n");
for (int i = 1; i <= n; i++) {
printf("%d", in[i]);
if (i < n) printf(" ");
}
printf("\n");
return 0;
}