这个题把我这菜鸡治的服服帖帖!
题意:
给定先序和后序
问中序是否唯一并输出其中任意一个中序序列
思路:
首先知道为啥没有中序序列不能为以确定一颗树的原因:对于先序序列,某个根节点右边都是(这个都是并不完全是从他到结尾的意思)他的孩子节点,我们选定他紧挨着右边的这个点,那这个点肯定就是他某个子树(不确定左右)的根节点root2,root2右边的所有点(所有定义同理)我们称为集合S1,然后再去看这个点root2在后序序列中的位置,如果他左边的点的个数与S1完全一样 那我们就无法区分这一些是左子树还是右子树
那么考虑解题思路,由于只要输出其中一个方案,所以假定为左孩子即可
每次都是递归求解当前区间
对于当前的区间,以下范围都局限于当前区间
先序序列第一个点肯定是根节点,然后他右边的点都是他的子节点,我们选定他紧挨着右边的这个点,那这个点肯定就是他某个子树(不确定左右)的根节点root,我们在后序序列中遍历寻找这个根节点root,那么在后序遍历范围0~idx就是左子树的节点,idx+1到r范围内是右子树的节点,但是如果右子树节点数为0,也就是说从root到R的点等于从0到idx的点,我们就无法确定这是左子树还是右子树
剩下的递归建树就好。
这个题只需要边递归边记录中序就可以了。
分享一个跟网上绝大多数博客不太一样的写法
#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<stack>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e2+5;
int pre[maxn],post[maxn];
vector<int> in;
int flag=1,k,n;
void build(int len,int pre[],int post[])
{
if(len==0)
return;
if(len==1)
{
in.push_back(pre[0]);
return;
}
int i;
for(i=0;i<len;i++)
if(post[i]==pre[1])
break;
if(i==len-2)
flag=0;
build(i+1,pre+1,post);
in.push_back(pre[0]);
build(len-i-2,pre+2+i,post+i+1);
}
int main()
{
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]);
build(n,pre,post);
if(flag)
printf("Yes\n");
else printf("No\n");
for(int i=0;i<n;i++)
printf("%d%c",in[i]," \n"[i==n-1]);
return 0;
}
然后自己又写了一发跟网上一样的写法
#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<stack>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1e2+5;
int pre[maxn],post[maxn];
vector<int> in;
int flag=1,k,n;
void build(int prel,int prer,int postl,int postr)
{
if(prel>prer)
return;
if(prel==prer)
{
in.push_back(pre[prel]);
return;
}
int i;
for(i=postl;i<=postr;i++)
if(post[i]==pre[prel+1])
break;
int num=i-postl;
if(prer-prel-1==num)
flag=0;
build(prel+1,prel+num+1,postl,i);
in.push_back(pre[prel]);
build(prel+num+2,prer,i+1,postr-1);
}
int main()
{
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]);
build(0,n-1,0,n-1);
if(flag)
printf("Yes\n");
else printf("No\n");
for(int i=0;i<n;i++)
printf("%d%c",in[i]," \n"[i==n-1]);
return 0;
}