题目大意:给你一棵树的层次遍历和前序遍历,让你复原这棵树
思路:这是分类讨论的题,感觉挺难的
此题的关键,是要把已知的两次遍历配合起来。
考虑前序遍历中的前后两个点,分别记作A和B,那B点可能是A点的兄弟、儿子或者其他(叔叔之类)
而通过层次遍历可以知道两个点中谁更深,如果B点更深,那B点肯定是A的儿子;
如果B点和A点一样深,那B点可能是儿子,也可能是兄弟,根据节点编号大小讨论一下就好
如果B点没有A点深,那B点只能是A点的长辈
所以,我们可以用栈模拟前序遍历的过程,从而找到每个节点的父亲
#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<stack> using namespace std; const int N=1000+4; int n,a[N],b[N]; stack<int>h; vector<int>g[N]; int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) g[i].clear(); int v; for(int i=1;i<=n;i++) scanf("%d",&v), a[v]=i;//节点在层次遍历中的位置 for(int i=1;i<=n;i++) scanf("%d",&b[i]); h.push(b[1]);//根节点 int tmp; for(int i=2;i<=n;i++) { while(a[b[i]]<a[h.top()])//需向上追溯 h.pop(); if(a[b[i]]==a[h.top()]+1 && b[i]>h.top() && h.top()!=b[1]) h.pop();//找到兄弟拉 //既可以是兄弟也可以是父子的情况,我把它归类到兄弟了 //只要不满足是兄弟,就一定是父子 g[h.top()].push_back(b[i]); h.push(b[i]); } int sz; for(int i=1;i<=n;i++) { printf("%d:",i); sort(g[i].begin(),g[i].end()); sz=g[i].size(); for(int j=0;j<sz;j++) printf(" %d",g[i][j]); printf("\n"); } } return 0; }