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

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

  已知前序遍历和后序遍历序列,是无法确定一棵二叉树的,原因在于如果只有一棵子树可能是左孩子也有可能是右孩子。由于只要输出其中一个方案,所以假定为左孩子即可。下面就是如何根据前序和后序划分出根节点和左右孩子,这里需要定义前序和后序的区间范围,分别为[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. Android 生态消息推送平台介绍

    一.手机厂商平台 华为消息推送服务 华为推送(Push)是为开发者提供的消息推送平台,建立了从云端到手机端的消息推送通道,使应用可以将最新信息及时通知用户,从而构筑良好的用户关系,提升用户的感知和活跃 ...

  2. 12.SolrCloud原理

    转载自http://blog.csdn.net/u011026968/article/details/50336709 内容涉及:SolrCloud的基础知识.架构.索引创建和更新.查询.故障恢复.负 ...

  3. python 之 string() 模块

    common string oprationsimport string1. string constants(常量) 1) string.ascii_letters       The concat ...

  4. BZOJ 1085 骑士精神 迭代加深搜索+A*

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1085 题目大意: 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个 ...

  5. 7、JVM--虚拟机类加载机制

    7.1.概述 再类文件结构中 在Class文件中描述的各种信息,最终都需要加载到虚拟机中之后才能运行和使用. 而虚拟机如何加载这些Class文件?Class文件中的信息进入到虚拟机后会发生什么变化? ...

  6. C++与C#互调dll的实现步骤

    这篇文章主要介绍了C++与C#互调dll的实现步骤,dll动态链接库的共享在一些大型项目中有一定的应用价值,需要的朋友可以参考下 本文实例展示了C++与C#互调dll的实现步骤,在进行大型项目共享dl ...

  7. 节点的启动与关闭 ros::init()解析(c++)

    1.初始化roscpp 节点 ros::init()  API链接:http://docs.ros.org/api/roscpp/html/init_8h.html 在node代码中在调用其它rosc ...

  8. JS省市区联动效果

    省市区联动下拉效果在WEB中应用非常广泛,尤其在电商网站最为常见.一般使用Ajax实现无刷新下拉联动.利用jQuery,通过读取JSON数据,实现无刷新动态下拉省市二(三)级联动效果. 首先我们可以看 ...

  9. 字典树Trie树

    摘自大佬博客 https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html 给出n个单词和m个询问1.查询某个前缀是否出现过2.查询某个单词是否出现过 ...

  10. day08(补)

    今日学习内容 1.文件重写方法 2.函数基本知识 文件处理: 打开文件 读/写文件 关闭文件 文件指针移动,只有t模式下的read(n),n代表的字符个数其余都是以字节为单位 f.seek有两个参数( ...