PAT Advance 1119 Pre- and Post-order Traversals (30) [树的遍历,前序后序转中序]
题目
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
题目分析
已知前序和后序,打印中序
- 若中序唯一,打印Yes和唯一中序序列
- 若中序不唯一,打印No和任意一个中序序列
注:如何判断中序是否唯一?
在前序序列中,如果当前右子树根节点(当前后序序列倒数第二个节点)左边只有一个节点,则说明当前右子树根节点既可以为其父节点的左孩子节点,也可为其父节点的右孩子节点
如:前序序列1 2 3 4,后序序列2 4 3 1
第一轮:前序序列为1 2 3 4,后序序列为2 4 3 1。后序序列最后一个节点1为根节点,后序序列倒数第二个节点3为1的右子树根节点,查找其在前序序列中其左边有两个节点1,2,则1为根节点,2为1的左子节点,3为1的右子节点
左递归:(处理第一轮中的左子树):前序序列为2,后序序列为2
右递归:(处理第一轮中的右子树):前序序列为3 4,后序序列为4 3。后序序列最后一个节点3为本轮根节点,后序序列倒数第二个节点4为3的右子树根节点,查找其在前序序列中其左边只有一个节点3,3为根节点,4既可以为3的左子节点也可以为3的右子节点(二叉树不唯一,即:中序序列不唯一)
解题思路
思路 01
- 后序序列倒数第一个节点为当前根节点,后序序列倒数第二个节点为当前根节点的右子树根节点
- 先处理当前根节点的左子树,找到最左节点后添加到in中序序列中
- 将1中最左节点的根节点添加到in中序序列中
- 再处理当前根节点的右子树,将其看做一棵树,处理方式同步骤1,2,3(找最左节点及其根节点并处理其右子树)
注:
第一轮
preOrder: 1 2 3 4 6 7 5
postOrder: 2 6 7 4 5 3 1
当前根节点为1,右子树根节点为3,由其在前序序列中的位置可看出,右子树节点包含:3 4 6 7 5,左子树只有一个节点为2
将2入中序序列,之后将1入中序序列(此刻中序序列为:2 1)
第二轮
preOrder: 3 4 6 7 5
postOrder: 6 7 4 5 3
当前根节点为3,右子树只有一个节点为5,由其在前序序列中的位置可看出,左子树根节点为4,左子树节点包含:4 6 7
----递归(处理左子树):找最左节点为6,其根为4,最左节点的父节点的右节点为叶子节7,依次入中序序列(此刻中序序列为:2 1 6 4 7)
继续处理:根节点3入中序序列,其唯一右子树节点5入中序序列(此刻中序序列为:2 1 6 4 7 3 5)
思路 02(容易理解)
- 后序序列倒数第一个节点为当前根节点,后序序列倒数第二个节点为当前根节点的右子树根节点
- 递归查找当前根节点的左右子节点
- 若遇到右子节点前只有一个根节点的情况,说明该右子节点也可为其根节点的左子节点(即:二叉树不唯一,中序序列不唯一),unique标识置为false,并将该节点假设为其根节点的右子节点处理
易错点
1. 最后输出完毕后,必须打印一个换行,否则所有测试点格式错误
Code
Code 01
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 30;
int n,pre[maxn],post[maxn],index;
bool unique=true;
vector<int> in;
void inOrder(int preL,int preR,int postL,int postR) {
// if(preL>preR)return;
if(preL==preR) {
in.push_back(pre[preL]);
return;
}
if(pre[preL]==post[postR]) {
int k=preL+1;
while(k<preR&&pre[k]!=post[postR-1])k++;
if(k-preL>1) {
inOrder(preL+1,k-1,postL,postL+(k-preL-1)-1);
} else {
unique=false;
}
in.push_back(post[postR]);
inOrder(k,preR,postL+(k-preL-1),postR-1);
}
}
int main(int argc,char * argv[]) {
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]);
inOrder(0,n-1,0,n-1);
printf("%s\n%d", unique == true ? "Yes" : "No", in[0]);
for (int i = 1; i < in.size(); i++)
printf(" %d", in[i]);
printf("\n"); //测试发现:最后必须输出换行,否则全部格式错误
return 0;
}
Code 02(容易理解)
#include <iostream>
using namespace std;
const int maxn = 30;
int n,pre[maxn],post[maxn],index;
bool unique=true;
struct node {
int data;
node * left;
node * right;
};
node * create(int preL,int preR,int postL,int postR) {
if(preL>preR)return NULL;
node * root = new node;
root->data=post[postR];
root->left=NULL;
root->right=NULL;
if(preL==preR)return root;
int k=preL+1;
while(k<=preR&&pre[k]!=post[postR-1])k++;
if(k-preL>1) {
root->left=create(preL+1,k-1,postL,postL+(k-preL-1)-1);
root->right=create(k,preR,postL+(k-preL-1),postR-1);
} else {
unique = false;
root->right=create(k,preR,postL+(k-preL-1),postR-1);
}
return root;
}
void inOrder(node * root) {
if(root==NULL)return;
inOrder(root->left);
if(index<n-1)printf("%d ",root->data);
else printf("%d\n",root->data); //测试发现:最后欧必须输出换行,否则全部格式错误
index++;
inOrder(root->right);
}
int main(int argc, char * argv[]) {
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]);
node * root = create(0,n-1,0,n-1);
printf("%s\n",unique?"Yes":"No");
inOrder(root);
return 0;
}
PAT Advance 1119 Pre- and Post-order Traversals (30) [树的遍历,前序后序转中序]的更多相关文章
- PAT Advanced 1151 LCA in a Binary Tree (30) [树的遍历,LCA算法]
题目 The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both ...
- PAT A 1119. Pre- and Post-order Traversals (30)【二叉树遍历】
No.1119 题目:由前序后序二叉树序列,推中序,判断是否唯一后输出一组中序序列 思路:前序从前向后找,后序从后向前找,观察正反样例可知,前后序树不唯一在于单一子树是否为左右子树. 判断特征:通过查 ...
- 【PAT甲级】1119 Pre- and Post-order Traversals(前序后序转中序)
[题目链接] [题意] 根据二叉树的前序和后序序列,如果中序序列唯一,输出Yes,如果不唯一输出No,并输出这个中序序列. [题解] 众所周知,二叉树是不能够根据前序和中序建立的,为什么呢?首先需要明 ...
- PAT 甲级 1020 Tree Traversals (25 分)(二叉树已知后序和中序建树求层序)
1020 Tree Traversals (25 分) Suppose that all the keys in a binary tree are distinct positive integ ...
- PAT Advanced 1020 Tree Traversals (25) [⼆叉树的遍历,后序中序转层序]
题目 Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder an ...
- PAT Advanced 1053 Path of Equal Weight (30) [树的遍历]
题目 Given a non-empty tree with root R, and with weight Wi assigned to each tree node Ti. The weight ...
- PAT甲题题解-1119. Pre- and Post-order Traversals (30)-(根据前序、后序求中序)
(先说一句,题目还不错,很值得动手思考并且去实现.) 题意:根据前序遍历和后序遍历建树,输出中序遍历序列,序列可能不唯一,输出其中一个即可. 已知前序遍历和后序遍历序列,是无法确定一棵二叉树的,原因在 ...
- PAT 甲级 1021 Deepest Root (并查集,树的遍历)
1021. Deepest Root (25) 时间限制 1500 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A graph ...
- 1020. Tree Traversals (25) ——树的遍历
//题目 通过后续遍历 中序遍历 得出一棵树 ,然后按树的层次遍历打印 PS:以前对于这种用指针的题目是比较头痛的,现在做了一些链表操作后,感觉也不难 先通过后续中序建一棵树,然后通过BFS遍历这棵树 ...
随机推荐
- java.neo的ByteBuffer与Netty 的ByteBuf
JDK的ByteBuffer的缺点: 1.final byte[] hb;这是JDKde ByteBuffer对象中用于存储数据的对象声明;可以看到,其字节数组是被声明为final的,也就是长度是固定 ...
- dede开启会员功能
登陆后台,找到菜单里面的系统基本参数设置>会员设置>开启会员功能,选择“是”,保存即可
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-edit
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- js基础学习之-js对象的属性
Js属性 1. 设置属性 1) 对象. 2) 对象[‘属性名’] 3) GetAttribute函数 2. 获取属性 1) 变量=对象. 2) 变量=对象[‘属性名’] 3) GetAt ...
- C++ 管道
// PipeServer.cpp : Defines the entry point for the console application. // #include "stdafx.h& ...
- Jetson TX2 安装JetPack3.3教程
Jetson TX2 刷机教程(JetPack3.3版本) 参考网站:https://blog.csdn.net/long19960208/article/details/81538997 版权声明: ...
- openstack trove实例状态转换条件--Mitaka版本
今天研究了一下trove的instance状态转换条件.发现其实设计的挺复杂的.后来思考了一下这样设计的原因.我觉得大致是因为,如果instance的状态全部来自于instance上跑的数据库服务本身 ...
- VNC连接桌面
1.#yum -y install vnc *vnc-server* 2.修改VNCServer主配置文件 #vim /etc/sysconfig/vncservers 复制最后两行并去掉行首注释符, ...
- Sublime Text与LaTeX的结合
1.通过Command Palette安装LaTeXTools 2.通过Command Palette查找LaTeXTools: Reconfigure and migrate settings,回车
- 自定义环形进度条RoundProgressBar
一.效果图: Canvas画圆环说明: 圆环宽度不必在意,只是画笔宽度设置后达到的效果. 二.实现步骤 1.自定义View-RoundProgressBar 2.设置属性resources(decle ...