这道题给出前序遍历、后序遍历,要求你求出中序遍历。
我的思路是:根据前序遍历和后序遍历建树,然后中序遍历,求出答案。
那么如何建树呢?从左到右遍历前序遍历数组中的全部节点,对于当前节点,检查它和上一个节点之间的关系。关系可以分为两大类:
-
如果当前节点的后序遍历下标在上一个节点的左边,那么当前节点是上一个节点的子节点。那么,是左儿子还是右儿子呢?
- 如果在后序遍历序列中,当前节点的下标等于上一个节点的下标减一,那么不确定是左儿子还是右儿子,树不唯一,在我的算法中,统一都设为左儿子,这对后续计算有帮助。
- 如果在后序遍历序列中,当前节点的下标不等于上一个节点的下标减一,那么是左儿子。
-
如果当前节点的后序遍历序列下标在上一个节点的右边,那么当前节点可能是上一个节点的兄弟节点,也可能是上一个节点的父亲、爷爷、曾祖父……的兄弟节点。具体是哪一个呢?这就要在建树的时候,多定义一个域保存全部节点的父节点了。从当前节点的父亲节点开始向上寻找,寻找到的第一个还没有右儿子节点,且在后序遍历数组中下标大于当前节点的节点,就是当前节点的父节点,直接把当前节点放在它的右儿子处即可。
本题注意的地方:
- 最后输出的时候,说了不可以有多余空格,但是我即使控制了不可以有多余空格,还是格式错误,最后找了网上的资料,才发现是还需要输出回车,额,说实话,pat考试要是遇到这样的题,那还不得自闭死
- 保存数据的时候,要保存左儿子,右儿子,父亲,以及节点的id,虽然题目中给出的序列中,节点大小全是1到n的,但是实际上可能并不是这样,所以不可以把输入的序列中的节点的值当作下标来使用,需要作为id保存起来。
- 本题中n的范围是30,数组没必要开成我这么大,我只是想开大一点试试而已,但是并没有多过一个点,我也懒得改回去了
- 我是利用递归实现的建树,但是我的思路其实利用数组循环也可以实现。
- 在最后递归中序遍历输出答案的时候,由于不能输出最后一个空格,要把答案保存起来,统一输出。
#include <iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstdlib>
#include<queue>
#include<cstring>
#include<set>
#include<list>
#include<unordered_set>
using namespace std;
int n;
int qian[100010],hou[100010];
struct Node
{
int l=0,r=0,id=0,fa=0,houIndex=0;
}t[100010];
int equalIndex[100010];
int cnt=0;
bool ans=true;
void search(int cnt1,int lastQianIndex,int lastHouIndex,int qianIndex,int houIndex)
{
if(qianIndex>n)return;
if(lastQianIndex==-1)
{
cnt++;
t[cnt].id=qian[qianIndex];
t[cnt].houIndex=houIndex;
t[cnt].fa=-1;
search(cnt,qianIndex,equalIndex[qianIndex],qianIndex+1,equalIndex[qianIndex+1]);
}
else{
if(houIndex<lastHouIndex)
{
if(houIndex==lastHouIndex-1)
{
ans=false;
cnt++;
t[cnt].id=qian[qianIndex];
t[cnt].fa=cnt1;
t[cnt1].l=cnt;
t[cnt].houIndex=houIndex;
}
else{
cnt++;
t[cnt].id=qian[qianIndex];
t[cnt].houIndex=houIndex;
t[cnt].fa=cnt1;
t[cnt1].l=cnt;
}
search(cnt,qianIndex,equalIndex[qianIndex],qianIndex+1,equalIndex[qianIndex+1]);
}
else
{
int father=t[cnt1].fa;
while(true)
{
if(t[father].r==0&&t[father].houIndex>houIndex)
{
cnt++;
t[cnt].id=qian[qianIndex];
t[cnt].fa=father;
t[cnt].houIndex=houIndex;
t[father].r=cnt;
break;
}
else{
father=t[father].fa;
}
}
search(cnt,qianIndex,equalIndex[qianIndex],qianIndex+1,equalIndex[qianIndex+1]);
}
}
}
vector<int>ansV;
void inOrder(int curr)
{
if(t[curr].l>0)
{
inOrder(t[curr].l);
}
ansV.push_back(t[curr].id);
if(t[curr].r>0)
{
inOrder(t[curr].r);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&qian[i]);
for(int i=1;i<=n;i++)
scanf("%d",&hou[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
if(hou[j]==qian[i])
{
equalIndex[i]=j;
break;
}
}
search(cnt,-1,-1,1,equalIndex[1]);
if(ans)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
inOrder(1);
for(int i=0;i<ansV.size()-1;i++)
cout<<ansV[i]<<" ";
cout<<ansV.back()<<endl;
}