PAT2019春7-4 Structure of a Binary Tree (30 分)

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, a binary tree can be uniquely determined.

Now given a sequence of statements about the structure of the resulting tree, you are supposed to tell if they are correct or not. A statment is one of the following:

  • A is the root
  • A and B are siblings
  • A is the parent of B
  • A is the left child of B
  • A is the right child of B
  • A and B are on the same level
  • It is a full tree

Note:

  • Two nodes are on the same level, means that they have the same depth.
  • full binary tree is a tree in which every node other than the leaves has two children.

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 postorder sequence and the third line gives the inorder sequence. All the numbers in a line are no more than 10​3​​ and are separated by a space.

Then another positive integer M (≤30) is given, followed by M lines of statements. It is guaranteed that both A and B in the statements are in the tree.

Output Specification:

For each statement, print in a line Yes if it is correct, or No if not.

Sample Input:

9
16 7 11 32 28 2 23 8 15
16 23 7 32 11 2 28 15 8
7
15 is the root
8 and 2 are siblings
32 is the parent of 11
23 is the left child of 16
28 is the right child of 2
7 and 11 are on the same level
It is a full tree

Sample Output:

Yes
No
Yes
No
Yes
Yes
Yes

这题在考场上因为自己没注意pretravel里面参数parent一开始为负数,偏偏dev还能运行,提交就运行时错误,直接全绿,气哭,后来用了VS知道哪儿错了,气得哭笑不得,加了一句if(parent!= -1)就直接AC了,这种题做的时候千万别慌,真的,别慌,一步步来,上次PAT的第二题也是这种,经常是0分和满分的区别,做不出来很容易爆炸。默念“比的是心态 ”会好很多。

解题思路:

首先由post和in,总有种上次LCA的感觉,其次7中字符串需要处理,先看看他们的不同。

接着先判断字符串:

It is a full tree最容易判断,看第一个字母是不是数字。

A is the root 以及 A and B are siblings 以及A and B are on the same level可以根据最后一个字母进行判断

剩余三个都是通过中间一个字母进行判断。 

然后想想怎么处理:

A is the root  只要比较a是否与post的最后一个数相等即可。

A and B are siblings  比较A和B的父亲节点是否相等

A is the parent of B  比较B的父亲节点是否为A

A is the left child of B  比较B的左孩子是否为A

A is the right child of B  比较B的右孩子是否为A

A and B are on the same level  比较A和B是否在同一层

It is a full tree  判断所有的节点是否是要么有两个孩子节点,要么是叶子节点

现在基本有分寸了,知道我们在遍历的时候需要保存每个节点的父亲节点,层数,孩子节点的个数,本身是左孩子还是右孩子。另外本题比较友善的地方是所有的节点数值是唯一的,而且不超过1000, 所以本题map都省了。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
vector<int>post(35), in(35), levelnum(1005, -1), sub(1005, -1), father(1005, -1), childcnt(1005, 0);
int n, m;
bool flag = true;
void pretravel(int inleft, int inright, int postright, int level, int parent, int index){
	if(inleft > inright)
		return;
	int i = inleft;
	while(in[i] != post[postright])
		++ i;
	if(parent!= -1)
		++ childcnt[parent];
	sub[post[postright]] = index;
	father[post[postright]] = parent;
	levelnum[post[postright]] = level;
	pretravel(inleft, i - 1, postright - inright + i - 1, level + 1, post[postright], 0);
	pretravel(i + 1, inright, postright - 1, level + 1, post[postright], 1);
}
int main(){
	scanf("%d", &n);
	for(int i = 0; i < n; ++ i)
		scanf("%d", &post[i]);
	for(int i = 0; i < n; ++ i)
		scanf("%d", &in[i]);
	pretravel(0, n - 1, n -1, 0, -1, -1);
	for(int i = 0; i < 1005; ++ i)
		if(childcnt[i] == 1){
			flag = false;
			break;
		}
	scanf("%d\n", &m);
	for(int i = 0; i < m; ++ i){
		string s;
		getline(cin, s);
		if(!isdigit(s[0]))
			printf("%s\n", flag == true ? "Yes" : "No");
		else{
			int a, b;
			string temp;
			int j = 0;
			while(isdigit(s[j])) 
				temp += s[j++];
			a = stoi(temp);
			if(s[s.length() - 1] == 't')
				printf("%s\n",a == post[n - 1] ? "Yes" : "No");
			else if(isdigit(s[s.length() - 1])){
				temp = "";
				int tempx = s.length() - 1;
				while(isdigit(s[tempx]))
					temp += s[tempx--];
				reverse(temp.begin(), temp.end());
				b = stoi(temp);
				j += 8;
				if(s[j] == 'p')
					printf("%s\n",a == father[b] ? "Yes" : "No");
				else if(s[j] == 'l')
					printf("%s\n",father[a] == b && sub[a] == 0? "Yes" : "No");
				else if(s[j] == 'r')
					printf("%s\n",father[a] == b && sub[a] == 1 ? "Yes" : "No");
			}
			else{
				j += 5;
				temp = "";
				while(isdigit(s[j]))
					temp += s[j++];
				b = stoi(temp);
				if(s[s.length() - 1] == 's')
					printf("%s\n",father[a] == father[b] ? "Yes" : "No");
				else
					printf("%s\n",levelnum[a] == levelnum[b] ? "Yes" : "No");
			}
		}
	}
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值