(先说一句,题目还不错,很值得动手思考并且去实现。)

题意:根据前序遍历和后序遍历建树,输出中序遍历序列,序列可能不唯一,输出其中一个即可。  

  已知前序遍历和后序遍历序列,是无法确定一棵二叉树的,原因在于如果只有一棵子树可能是左孩子也有可能是右孩子。由于只要输出其中一个方案,所以假定为左孩子即可。下面就是如何根据前序和后序划分出根节点和左右孩子,这里需要定义前序和后序的区间范围,分别为[preL,preR],[postL,postR]。  

  一开始区间都为[1,n],可以发现前序的第一个和后序的最后一个为根节点root,前序的第二个值val为其某子树的根节点(但还无法确定是左孩子or右孩子)。在后序中找对应的值所在的位置postIdx,则postIdx之前的节点均为val的孩子节点,统计其个数num。那么我们就可以划分区间:  

若num个数=preR-preL-1,即val后面的个数都是其子节点,那么二叉树不唯一,将其作为root的左子树处理。

否则划分为左子树区间和右子树对应的前序和后序区间,顺便更新下root的左孩子preL+1,右孩子preL+num+2:
preOrder:[preL+1,preL+num+1],postOrder:[postL,postIdx];
preOrder:[preL+num+2,preR],postOrder:[postIdx+1,postR-1];
然后递归划分即可

拿样例举例:
1 (2) [3 {4 6 7} <5>]
(2) [{6 7 4} <5> 3] 1
不同的括号对应不同的子树区间
第一次递归划分了(2)-(2),[3 4 6 7 5]-[6 7 4 5 3]
由于(2)只有一棵,不继续划分。
第二次递归划分了{4 6 7}-{6 7 4},<5>-<5>
第三次递归划分了(6)-(6),(7)-(7)
结束

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h> using namespace std;
const int maxn=;
int preOrder[maxn];
int postOrder[maxn];
bool isUnique=true;
struct Node{
int left=-,right=-;
}node[maxn]; /*
[preL,preR] is current sequence interval of pre-order
[postL,postR] is current sequence interval of post-order
*/
void build(int preL,int preR,int postL,int postR){
if(preL>=preR){
return;
}
int fa=preL;
//前序遍历的第一个为根节点,第二个为子树的根节点,可能是左孩子也可能是右孩子
int val=preOrder[preL+];
int postIdx;
for(int i=postL;i<postR;i++){
if(val==postOrder[i]){
postIdx=i; //val在后序遍历中的索引
break;
}
}
int num=postIdx-postL; //以val为根节点的子树节点个数
//即以val为根节点的子树只有一棵孩子,那么既可以为左孩子也可以为右孩子,所以不唯一
if(preR-preL-==num){
isUnique=false;
}
node[fa].left=preL+; //不唯一的话,看做左孩子
build(preL+,preL+num+,postL,postIdx);
//如果以preL+1为根节点的子树的节点个数小于fa的所有子树节点的个数,说明fa还有右孩子
if(preR-preL->num){
node[fa].right=preL+num+;
build(preL+num+,preR,postIdx+,postR-);
}
} bool first=true;
void inOrder(int root){
if(root==-){
return;
}
inOrder(node[root].left);
if(first){
first=false;
printf("%d",preOrder[root]);
}
else
printf(" %d",preOrder[root]);
inOrder(node[root].right);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&preOrder[i]);
for(int i=;i<=n;i++)
scanf("%d",&postOrder[i]);
build(,n,,n);
if(isUnique)
printf("Yes\n");
else
printf("No\n");
inOrder();
printf("\n"); //否则格式错误
return ;
}

PAT甲题题解-1119. Pre- and Post-order Traversals (30)-(根据前序、后序求中序)的更多相关文章

  1. PAT甲题题解1099. Build A Binary Search Tree (30)-二叉树遍历

    题目就是给出一棵二叉搜索树,已知根节点为0,并且给出一个序列要插入到这课二叉树中,求这棵二叉树层次遍历后的序列. 用结构体建立节点,val表示该节点存储的值,left指向左孩子,right指向右孩子. ...

  2. PAT甲题题解-1115. Counting Nodes in a BST (30)-(构建二分搜索树+dfs)

    题意:给出一个序列,构建二叉搜索树(BST),输出二叉搜索树最后两层的节点个数n1和n2,以及他们的和sum: n1 + n2 = sum 递归建树,然后再dfs求出最大层数,接着再dfs计算出最后两 ...

  3. PAT甲题题解-1064. Complete Binary Search Tree (30)-中序和层次遍历,水

    由于是满二叉树,用数组既可以表示父节点是i,则左孩子是2*i,右孩子是2*i+1另外根据二分搜索树的性质,中序遍历恰好是从小到大排序因此先中序遍历填充节点对应的值,然后再层次遍历输出即可. 又是一道遍 ...

  4. PAT甲题题解-1030. Travel Plan (30)-最短路+输出路径

    模板题最短路+输出路径如果最短路不唯一,输出cost最小的 #include <iostream> #include <cstdio> #include <algorit ...

  5. PAT甲题题解-1068. Find More Coins (30)-dp,01背包

    一开始没多想,虽然注意到数据N<=10^4的范围,想PAT的应该不会超时吧,就理所当然地用dfs做了,结果最后一组真的超时了.剪枝啥的还是过不了,就意识到肯定不是用dfs做了.直到看到别人说用0 ...

  6. PAT甲题题解-1003. Emergency (25)-最短路径+路径数目

    给出n个城市,m条边,起始点c1和目的点c2接下来给出n个城市的队伍数以及m条双向边问你求c1到c2的所有最短路径数目,以及其中经过的最多队伍数 先最短路dijkstra,同时建立vector数组pr ...

  7. PAT甲题题解-1008. Elevator (20)-大么个大水题,这也太小瞧我们做题者的智商了

    如题... #include <iostream> #include <cstdio> #include <algorithm> #include <cstr ...

  8. PAT甲题题解-1010. Radix (25)-二分搜索

    题意:给出n1和n2,以及其中一个数的进制,问另一个数是多少进制的情况下,才会是两个数相等.不存在的话,则输出Impossible 这题思路很简单,但是要考虑的比较多,在简单题里面算是比较好的. 有两 ...

  9. PAT甲题题解-1011. World Cup Betting (20)-误导人的水题。。。

    题目不严谨啊啊啊啊式子算出来结果是37.975样例输出的是37.98我以为是四舍五入的啊啊啊,所以最后输出的是sum+0.005结果告诉我全部错误啊结果直接保留两位小数就可以了啊啊啊啊 水题也不要这么 ...

随机推荐

  1. Kafka安装及使用

    zookeeper安装 下载地址:https://www.apache.org/dyn/closer.cgi/zookeeper/ 我这里下载的是zookeeper-3.4.13版本,下载后解压在E: ...

  2. MySQL 在各种程序语音的连接字符串(转)

    一.MySQL Connector/ODBC 2.50 (MyODBC 2.50)连接方式 1.本地数据库连接Driver={MySQL};Server=localhost;Option=16834; ...

  3. MySQL数据库常用操作和技巧

    MySQL数据库可以说是DBA们最常见和常用的数据库之一,MySQL的广泛应用,也使更多的人加入到学习它的行列之中.下面是老MySQL DBA总结的MySQL数据库最常见和最常使用的一些经验和技巧,分 ...

  4. 利用 share code 插件同步代码片段

    利用 Settings Sync可以同步 VS code 配置,但它只能同步插件,利用  Settings Sync 再配合 share code 插件可以同步自定义代码片段,可以把 VS code ...

  5. mysql用户创建与授权

    一. 创建用户 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明: username:你将创建的用户名 host:指定该用户 ...

  6. [转]深入理解MFC中程序框架

    最近抽空复习了一下MFC的内容,觉得一篇博文写的不错. 原文内容太多直接给出链接吧:深入理解MFC中程序框架 链接2:深入浅出话VC++(2)——MFC的本质 链接3:MFC单文档/视图结构穷追猛打

  7. Android 截取屏幕图片并保存

    Android市场上有很多屏幕截图软件,把当前屏幕截取出来并保存,这一节我们就来看看屏幕截图的具体实现. 操作步骤: 1.创建一片屏幕大小的缓冲区,用于存放屏幕大小的图片 Bitmap bitmap ...

  8. bat 传递超过10个参数(bat参数遍历)

    批处理文件中可引用的参数为%0~%9, %0是指批处理文件的本身,也可以说是一个外部命令:%1~%9是批处理参数,也称形参:而替换形参的实参若超过了批处理文件中所规定数值(9个)且想在批处理文件中应用 ...

  9. 20155204 王昊《网络对抗技术》EXP2 后门原理与实践

    20155204 王昊<网络对抗技术>EXP2 后门原理与实践 一.实验内容 准备工作(试用ncat.socat) 1. 使用netcat获取主机操作Shell,cron启动. 明确目标: ...

  10. WPF样式(Style)入门

    原文:WPF样式(Style)入门 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_34802416/article/details/78231 ...