剑指offer面试题:输入某二叉树的前序遍历和中序遍历,输出后序遍历
二叉树的先序,中序,后序如何遍历,不在此多说了。直接看题目描述吧(题目摘自九度oj剑指offer面试题6):
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的后序遍历序列。
- 输入:
输入可能包含多个测试样例,对于每个测试案例,
输入的第一行为一个整数n(1<=n<=1000):代表二叉树的节点个数。
输入的第二行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的前序遍历序列。
输入的第三行包括n个整数(其中每个元素a的范围为(1<=a<=1000)):代表二叉树的中序遍历序列。
输出
对应每个测试案例,输出一行:
如果题目中所给的前序和中序遍历序列能构成一棵二叉树,则输出n个整数,代表二叉树的后序遍历序列,每个元素后面都有空格。
如果题目中所给的前序和中序遍历序列不能构成一棵二叉树,则输出”No”。
下面看一下解题思路:
二叉树的问题,我们首先想到递归思想,即大问题的解题思路和小问题的解决思路是一样的。先来分析二叉树的先序和中序遍历序列能给我们哪些有用的信息,首先先序遍历可以告诉我们二叉树的根节点(即先序遍历序列的第一个元素)。其次,我们可以通过查询得到二叉树的根节点在中序遍历序列中的位置(假设为L),那么中序遍历序列L之前的是左子树,之后的右子树。知道这两部分信息之后,我们在考虑后序遍历,对于一个二叉树来说,根节点是后序遍历的最后一个去遍历的节点。
经过以上分析,我们就可以这样解题了(如下图):
现在要考虑的是,先递归右子树还是左子树,因为后序遍历是先左后右,而我们现在是从后往前得到后序遍历序列,所以先递归右子树。还有一个问题,即什么时候不能构成二叉树,本人以为只要根节点在中序遍历序列中查找不到就不能构成二叉树。
题目就分析到这,下面给出C语言完整代码,在九度oj上已AC,代码如下:
#include<stdio.h>
#include<stdlib.h>
/*
*已知二叉树的先序和中序遍历,求后序遍历
*/
int pos[];
int n;
int flag=;
int locationInMid(int mid[],int ms,int me,int h)
{
int i;
for(i=ms;i<=me;++i)
{
if(mid[i]==h)
return i;
}
return -;
}
void postOrder(int pre[],int ps,int pe,int mid[],int ms,int me) //有待改进的地方,函数的参数可以简化,因为数组的地址是0号元素的地址,知道头结点在mid中的位置后,左右子树的个数即可得到
{
int hm=,cl=,cr=;
pos[--n]=pre[ps];
//--n;
hm=locationInMid(mid,ms,me,pre[ps]);
if(hm==-)
{
// printf("No\n");
flag=-;
return ;
}
else
{
cl=hm-ms;
cr=me-hm;
if(cr>)
postOrder(pre,ps+cl+,pe,mid,hm+,me);
if(cl>)
postOrder(pre,ps+,ps+cl,mid,ms,hm-);
}
return ;
}
int main()
{
int pre[];
int mid[];
int i,t;
while(scanf("%d",&n)!=EOF)
{
t=n;
for(i=;i<n;++i)
scanf("%d",&pre[i]);
for(i=;i<n;++i)
scanf("%d",&mid[i]);
postOrder(pre,,n-,mid,,n-);
if(flag==-)
{
printf("No\n");
flag=;
}
else
{
for(i=;i<t;++i)//注意:n是全局变量所以上一个语句执行完之后,n的值已经不是原来的n了,所以要用t保存n最初的值
printf("%d ",pos[i]);
printf("\n");
}
}
return ;
}
本题的代码并不是最简洁的,但最容易理解,其实ps,pe,ms,me四个变量并不完全需要,因为pre指向的pre[ps],而知道二叉树的节点个数和根节点在中序遍历中的位置即可求得左右子树的位置,大家可以思考一下,优化一下代码。
剑指offer面试题:输入某二叉树的前序遍历和中序遍历,输出后序遍历的更多相关文章
- C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解
剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...
- 剑指offer面试题6 重建二叉树(c)
- 剑指offer面试题6 重建二叉树(java)
注:(1)java中树的构建 (2)构建子树时可以直接利用Arrays.copyOfRange(preorder, from, to),这个方法是左开右闭的 package com.xsf.SordF ...
- 剑指Offer面试题:33.二叉树的深度
一.题目一:二叉树的深度 1.1 题目说明 题目一:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如下图中的二叉树的 ...
- 剑指Offer:面试题6——重建二叉树(java实现)
问题描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不包含重复的数字. 例如: 输入:前序{1,2,4,7,3,5,6,8},中序{4,7,2,1 ...
- 剑指Offer面试题:18.二叉树的镜像
一.题目:二叉树的镜像 题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像.例如下图所示,左图是原二叉树,而右图则是该二叉树的镜像. 该二叉树节点的定义如下,采用C#语言描述: public c ...
- 剑指Offer面试题:23.二叉树中和为某一值的路径
一.题目:二叉树中和为某一值的路径 题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.例如输入下图中二叉树和整数2 ...
- 剑指offer——面试题8:二叉树的下一个节点
// 面试题8:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针. ...
- 剑指Offer面试题15(Java版):链表中倒数第K个结点
题目: 输入一个链表.输出该链表中倒数第k哥结点. 为了符合大多数人的习惯,本题从1開始计数.即链表的尾结点是倒数第1个结点. 比如一个链表有6个结点.从头结点開始它们的值依次是1.2.3,4,5, ...
- 剑指offer面试题25:二叉树中和为某一值的路径
题目:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.从根节点开始往下一直到叶节点所经过的节点形成一条路径. 解题思路:当使用前序遍历的方式访问某一节点时,把该节点添加到路径上 ...
随机推荐
- Canvas学习笔记——动画环境中的边界
在动画中经常要处理边界问题,比如一个物体运动到了边界,要怎么处理才合适呢?通常有几种以下几种方式: 让物体消失 // > 16 & 0xff, g = color >> 8 ...
- Hadoop文档 索引
Hadoop中文文档 http://hadoop.apache.org/docs/r1.0.4/cn/index.html Hadoop资料整理 http://www.itpub.net/thread ...
- Android活动条(actionbar)使用具体解释(一)
活动条(ActionBar)是Android3.0的重要更新之中的一个.ActionBar位于传统标题的位置,其主要提供了例如以下功能: >显示选项菜单的菜单项,即激昂菜单项显示 ...
- CXF实战之自己定义拦截器(五)
CXF已经内置了一些拦截器,这些拦截器大部分默认加入到拦截器链中,有些拦截器也能够手动加入,如手动加入CXF提供的日志拦截器.也能够自己定义拦截器.CXF中实现自己定义拦截器非常easy.仅仅要继承A ...
- iOS8的UIPresentationController
本文转载至 http://kyfxbl.iteye.com/blog/2147888 从iOS8开始,controller之间的跳转特效,需要用新的API UIPresentationControll ...
- SAM4E单片机之旅——7、LED闪烁之TC中断
RTT主要用做一个全局的定时器,而且不太通用.现在尝试使用一个更为通用的定时器进行定时:定时计数器(Timer Counter, TC). TC提供了广泛的功能,主要可以分为对输入的测量,以及波形的输 ...
- NOTE:rfc5766-turn-server
NOTE:This project is active in Google code: http://code.google.com/p/rfc5766-turn-server/ 启动方法:./tur ...
- if __name__ == "__main__": 怎么理解?
参考:https://www.cnblogs.com/Neeo/p/9504779.html 总结: 1.防止模块间调用时,执行被调用模块实例化执行,换句话说,就是不要执行调用模块原来实例化的内容 2 ...
- Find out when memory leaks are a concern and how to prevent them
Handling memory leaks in Java programs Find out when memory leaks are a concern and how to prevent t ...
- Hadoop实战-Flume之Hello world(九)
环境介绍: 主服务器ip:192.168.80.128 1.准备apache-flume-1.7.0-bin.tar文件 2.上传到master(192.168.80.128)服务器上 3.解压apa ...