PAT 甲级 1119 Pre- and Post-order Traversals

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a845717607/article/details/87900115

1119 Pre- and Post-order Traversals (30 point(s))

Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determined by a given pair of postorder and inorder traversal sequences, or preorder and inorder traversal sequences. However, if only the postorder and preorder traversal sequences are given, the corresponding tree may no longer be unique.

Now given a pair of postorder and preorder traversal sequences, you are supposed to output the corresponding inorder traversal sequence of the tree. If the tree is not unique, simply output any one of them.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤ 30), the total number of nodes in the binary tree. The second line gives the preorder sequence and the third line gives the postorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, first printf in a line Yes if the tree is unique, or No if not. Then print in the next line the inorder traversal sequence of the corresponding binary tree. If the solution is not unique, any answer would do. It is guaranteed that at least one solution exists. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input 1:

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

Sample Output 1:

Yes
2 1 6 4 7 3 5

Sample Input 2:

4
1 2 3 4
2 4 3 1

Sample Output 2:

No
2 1 3 4

经验总结:

众所周知,已知前序遍历序列和后序遍历序列,无法确定唯一的二叉树,但是,究其原因是啥,看到题目的我是萌比的,后来参考了大神的代码,才知道,无法确定唯一二叉树的原因,例:
pre:1 2 3 4 6 7 5  post:2 6 7 4 5 3 1  
1肯定是根,去掉根后pre:2 3 4 6 7 5 post:2 6 7 4 5 3 此时该如何下手呢?这里可以根据后序序列的规则“左右根”,利用 3(即后序序列的根结点所在位置的前一个元素), 在前序序列里搜索 3 的所在位置,如果3 在前序中与紧挨着根结点 1 ,那么根据前序序列规则 “根左右” ,可知3 有可能 为左分支,也有可能为右分支,无法根据序列确定;但是,如果3 没有紧挨着根结点1 ,就如此例子的情况,那么,就可以根据3的所在位置,划分根结点的左右分支,(因为没有紧挨着,所以3和1中间的结点就是1的左分支,这里有可能有疑问,3右边的都是右分支吗?这里你可以想一下,因为没有紧挨,所以有左分支,那么根据 “左右根” 的原则,3一定是右分支的根结点,那么其右分支的前序序列一定以3开头,所以,3后面的都是右分支)。从而继续再对左右分支进行划分,最终得到中序遍历序列~

AC代码

#include <cstdio>

const int maxn=40;
bool unique=true;
int in[maxn],pre[maxn],post[maxn],num=0,n;
void getin(int preL,int preR,int postL,int postR)
{
	if(preL==preR)
	{
		in[num++]=pre[preL];
		return ;
	}
	if(pre[preL]==post[postR])
	{
		int i=preL+1;
		for(;i<=preR;++i)
		{
			if(pre[i]==post[postR-1])
				break;
		}
		if(i-preL>1)
			getin(preL+1,i-1,postL,postL+i-preL-2);
		else
			unique=false;
		in[num++]=pre[preL];
		getin(i,preR,postL+i-preL-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]);
	getin(0,n-1,0,n-1);
	printf("%s\n",unique?"Yes":"No");
	for(int i=0;i<num;++i)
		printf("%d%c",in[i],i<num-1?' ':'\n');
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a845717607/article/details/87900115