每日一练——浪漫侧影 (25 分)

258 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情。​​

题目概述:

v.JPG

“侧影”就是从左侧或者右侧去观察物体所看到的内容。例如上图中男生的侧影是从他右侧看过去的样子,叫“右视图”;女生的侧影是从她左侧看过去的样子,叫“左视图”。

520 这个日子还在打比赛的你,也就抱着一棵二叉树左看看右看看了……

我们将二叉树的“侧影”定义为从一侧能看到的所有结点从上到下形成的序列。例如下图这棵二叉树,其右视图就是 { 1, 2, 3, 4, 5 },左视图就是 { 1, 6, 7, 8, 5 }。

fig.JPG

于是让我们首先通过一棵二叉树的中序遍历序列和后序遍历序列构建出一棵树,然后你要输出这棵树的左视图和右视图。

输入格式:

输入第一行给出一个正整数 N (≤20),为树中的结点个数。随后在两行中先后给出树的中序遍历和后序遍历序列。树中所有键值都不相同,其数值大小无关紧要,都不超过 int 的范围。

输出格式:

第一行输出右视图,第二行输出左视图,格式如样例所示。

输入样例:

8
6 8 7 4 5 1 3 2
8 5 4 7 6 3 2 1

输出样例:

R: 1 2 3 4 5
L: 1 6 7 8 5

感谢用户DSA修正数据!

分析

题意

  1. 根据后序遍历和中序遍历重建二叉树,并求出它的层序遍历。
  2. 左视图就是从根节点到最后一层叶子的每一层的第一个节点,右视图是末尾节点。按层输出即可。

思路

  1. 了解了后序遍历左子树->右子树->根节点的性质之后,我们可以逆向遍历后序遍历序列,最末尾的数字便是根节点的权值.
  2. 根据根节点的权值在中序遍历序列中找到根节点,根节点右边为右子树,左边为左子树,便可区分出左右子树.
  3. 先将右子树单独拎出来作为一个树,再将左子树拎出来.(因为逆向遍历后序序列顺序为根->右->左).
  4. 根据上面的方法进行递归,将递归次数作为层数,放入相应的队列中,并且记录最大层数.
  5. 将left==right设置为递归边界.(此时达到了叶子节点,返回)

代码:

#include<queue>
using namespace std;
int mid[20],post[20],x,n,maxn;
queue<int> q[20];
int shu(int left,int right,int index){
	int root;
	if(left==right)
	{
		if(maxn<index)
			maxn=index;
		return 0;
	}
		
	for(int i=left;i<right;i++){
		if(mid[i]==post[x])
		{
			root=i;
//			cout<<mid[i]<<' ';
			q[index].push(mid[i]);
			x--;
			break;
		}
			
	}
	shu(root+1,right,index+1);
	shu(left,root,index+1);
}

int main(){

	cin>>n;
	x=n-1;
	for(int i=0;i<n;i++)
		cin>>mid[i];
	for(int i=0;i<n;i++)
		cin>>post[i];
	shu(0,n,0);
	cout<<"R: ";
	for(int i=0;i<maxn;i++){
		cout<<q[i].front();
		if(i!=maxn-1)
			cout<<' ';
	}
		
	cout<<'\n';
	cout<<"L: ";
	for(int i=0;i<maxn;i++){
		cout<<q[i].back();
		if(i!=maxn-1)
			cout<<' ';
	}
    cout<<'\n';
		
}