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遍历这棵树 ...
随机推荐
- mysql limit查询入门
- ucosiii 移植
最近想在 f429 上面使用 mdk526 版本的 IDE,配合 HAL 和ucosiii.考虑到的方法是对比 v7 开发板的 ucosiii 和裸机程序,找出需要修改的地方,然后对比 v6 开发板的 ...
- 七、Vue组件库:Element、Swiper(轮播专用组件)
一.vue的Element组件库 官网:https://element.eleme.cn/#/zh-CN 1.1安装 推荐安装方法: 首先要进入项目目录 cnpm i element-ui -S 或 ...
- 时间戳和LocalDateTime和Date互转和格式化
一 前言 续上篇java8在日常开发中使用LocalDate和LocalTime[https://blog.csdn.net/youku1327/article/details/102771936]中 ...
- 18.swoole学习笔记--案例
<?php //创建webSocket服务器 $ws=); //open $ws->on('open',function($ws,$request){ echo "新用户 $re ...
- 箭头函数arrow funtion
1.定义一个匿名函数常规语法: function (x) { return x * x; } 2.该函数使用箭头函数可以使用仅仅一行代码搞定! x => x * x 箭头函数相当于匿名函数,并且 ...
- office(CVE-2012-0158)漏洞分析报告
2019/9/12 1.漏洞复现 ①发现崩溃 ②找到漏洞所在的函数,下断点,重新跑起来,单步调试,找到栈被改写的地方 ③分析该函数 把MSCOMCTL拖入IDA,查看该函数代码 ④查看调用栈,回溯. ...
- C++的随机数
C++产生随机数 C++中没有自带的random函数,要实现随机数的生成就需要使用rand()和srand(). 不过,由于rand()的内部实现是用线性同余法做的,所以生成的并不是真正的随机数,而是 ...
- 【Android】家庭记账本手机版开发报告六
一.说在前面 昨天 1.创建登入和注册界面:2.向数据库添加一张用户表 今天 用图标显示账单情况 问题 1.使用第三方库 hellochart,时添加依赖构建失败 2.在 chertFragmen ...
- UVA - 1643 Angle and Squares (角度和正方形)(几何)
题意:第一象限里有一个角,把n(n <= 10)个给定边长的正方形摆在这个角里(角度任意),使得阴影部分面积尽量大. 分析:当n个正方形的对角线在一条直线上时,阴影部分面积最大. 1.通过给定的 ...