剑指offer第二版面试题6:重建二叉树(JAVA版)
题目:输入某二叉树的前序遍历和中序遍历的结果,请重新构造出该二叉树。假设输入的前序遍历和中序遍历的结果中不包含重复的数字。例如输入的前序遍历序列为{1,2,4,7,3,5,6,8}和中序遍历为{4,7,2,1,5,3,6,8},则重建出二叉树并输出它的头结点。
前序遍历:根节点--》左节点--》右节点
中序遍历:左节点--》根节点--》右节点
后序遍历:左节点--》右节点--》根节点
在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但在中序遍历中,根节点的值在序列的中间,左子树的结点的值位于根节点的值的左边,而右子树的结点的值位于根节点的右边。因此我们需要扫描中序遍历序列,才能找到根节点的值。
如图所示,前序遍历序列的第一个数字1就是根节点的值。扫描中序遍历序列,就能确定根节点的值的位置。根据中序遍历的特点,在根节点的值1前面3个数字都是左子树结点的值,位于1后面的数字都是右子树结点的值。
由于中序遍历序列中,有3个数字是左子树结点的值,因此左子树总共有3个左子结点。同样,在前序遍历的序列中,根节点后面的3个数字就是3个左子树结点的值,再后面的所有数字都是右子树结点的值。这样我们就在前序遍历和中序遍历两个序列中,分别找到了左右子树对应的子序列。

然后再根据左子树的前序遍历和中序遍历找出根节点和左右子树,可以使用递归来完成,每次得到根节点
用左子树来举例:
第二次:
前序:247
中序:472
根节点2,由中序可知没有右节点
第三次:
前序:47
中序:47
根节点:4
没有了左子树,7为4的右节点
代码如下:
/**
* 树节点
*/
class BinaryTreeNode {
int value;
BinaryTreeNode leftNode;
BinaryTreeNode rightNode;
public BinaryTreeNode(int value){
this.value=value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public BinaryTreeNode getLeftNode() {
return leftNode;
}
public void setLeftNode(BinaryTreeNode leftNode) {
this.leftNode = leftNode;
}
public BinaryTreeNode getRightNode() {
return rightNode;
}
public void setRightNode(BinaryTreeNode rightNode) {
this.rightNode = rightNode;
} } public class RebuildTree {
/**
* 根据前序遍历和中序遍历重建二叉树
* */
public static BinaryTreeNode rebuildTree(int[] preOrder, int[] inOrder){
if (preOrder == null || inOrder == null || preOrder.length == 0 || inOrder.length == 0 || preOrder.length != inOrder.length) {
return null;
}
//根节点
BinaryTreeNode root=new BinaryTreeNode(preOrder[0]);
root.setLeftNode(null);
root.setRightNode(null);
//左子树节点的个数
int leftNum=0;
for(int i=0;i<inOrder.length;i++){
if(inOrder[i]==root.getValue()){
break;
}else{
leftNum++;
}
}
//右子树节点的个数
int rightNum=inOrder.length-1-leftNum; //重建左子树
while(leftNum>0){
//用来存放左子树的前序遍历
int leftPreOrder[]=new int[leftNum];
//用来存放左子树的中序遍历
int leftInOrder[]=new int[leftNum];
//赋值给左子树每个节点值,把左子树再独立成一棵树
for(int i=0;i<leftNum;i++){
leftPreOrder[i]=preOrder[i+1];
leftInOrder[i]=inOrder[i];
}
BinaryTreeNode leftRoot=rebuildTree(leftPreOrder, leftInOrder);
root.setLeftNode(leftRoot);
}
//重建右子树
while(rightNum>0){
//右子树的前序遍历
int rightPreOrder[]=new int[rightNum];
//右子树的中序遍历
int rightInOrder[]=new int[rightNum];
//赋值 for(int i=0;i<rightNum;i++){
rightPreOrder[i]=preOrder[i+1+leftNum];
rightInOrder[i]=preOrder[i+1+leftNum];
}
BinaryTreeNode rightNode=rebuildTree(rightPreOrder, rightInOrder);
root.setRightNode(rightNode);
} return root;
} public static void main(String[] args) {
// 二叉树的先序序列
int[] preOrder = { 1, 2, 4, 7, 3, 5, 6, 8 };
// 二叉树的中序序列
int[] inOrder = { 4, 7, 2, 1, 5, 3, 8, 6 };
BinaryTreeNode root = rebuildTree(preOrder, inOrder);
}
}
剑指offer第二版面试题6:重建二叉树(JAVA版)的更多相关文章
- 《剑指offer》面试题6 重建二叉树 Java版
(由一个二叉树的前序和中序序列重建一颗二叉树) 书中方法:我们要重建一棵二叉树,就要不断地找到根节点和根节点的左子结点和右子节点.注意前序序列, 它的第一个元素就是二叉树的根节点,后面的元素分为它的左 ...
- 剑指offer第二版面试题7:二叉树的下一个节点(JAVA版本)
题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 分析: 根据中序遍历的特点,要找到一个节点的下一个节点无非 ...
- 剑指offer第二版面试题4:替换空格(JAVA版)
题目:请实现一个函数,把字符串中的每个空格替换成“%20”.例如输入“We are happy”,则输出”We%20are%20happy”. 原因:在网络编程中,如果URL参数中含有特殊字符,如:空 ...
- 剑指offer第二版面试题5:从尾到头打印链表(JAVA版)
题目描述: 输入一个链表,从尾到头打印链表每个节点的值.返回新链表. import java.util.Stack; //定义链表结构 class ListNode { int value; List ...
- 剑指offer第二版面试题11:旋转数组的最小数字(JAVA版)
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数 ...
- 剑指offer第二版面试题10:斐波那契数列(JAVA版)
题目:写一个函数,输入n,求斐波那契数列的第n项.斐波那契数列的定义如下: 1.效率很低效的解法,挑剔的面试官不会喜欢 使用递归实现: public class Fibonacci { public ...
- 剑指offer第二版面试题9:用两个队列实现栈(JAVA版)
题目:用两个队列实现栈. 分析:通过一系列的栈的压入和弹出操作来分析用队列模拟一个栈的过程,如图所示,我们先往栈内压入一个元素a.由于两个队列现在都是空,我们可以选择把a插入两个队列中的任一个.我们不 ...
- 剑指offer第二版面试题8:用两个栈实现队列(JAVA版)
题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deletedHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能. 分析: 我们通过一个具体的例子来分析 ...
- 剑指offer第二版面试题3:二维数组中的查找(JAVA版)
题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 1 2 8 9 2 4 ...
随机推荐
- python requests函数封装方法
python requests函数封装方法 上代码 import requests import json """ 封装request请求, 1.post:my_pos ...
- 使用cookie来做身份认证 转载https://www.cnblogs.com/sheldon-lou/p/9545726.html
文章是msdn的官方文档,链接在这里.其实也有中文的文档,这里还是想做一个记录. 文章有asp.net core 2.x 和1.x 版本,我这里就忽略1.x了. 下面先说几点额外的东西有助于理解. A ...
- java %d %n \n
Java中,%d和%f分别用来表示输出时,替换整型输出和浮点型输出的占位符. 如: int a=28; float b = 13.0f; System.out.printf("整数是:%d% ...
- Supervisord rce(CVE-2017-11610)
POST /RPC2 HTTP/1.1 Host: localhost Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compati ...
- Haproxy+ssl+nvm+forever
1 nvm介绍 NVM(Node version manager)顾名思义,就是Node.js的版本管理软件,可以轻松的在Node.js各个版本间切换,项目源码在GitHub: #安装git客户端 [ ...
- 为什么javaBean要有get/set方法的设计
可以应对将来的修改,比如有一个以长度计算的项目开发好了,过段时间客户说这个项目要在美国上市,有了javaBean只要把所有以厘米计算的单位都乘以2.54转化为正确单位交给客户 public class ...
- spark复习总结02
1.spark执行原理图 spark程序启动后创建sparkContext作为程序的入口,sparkContext可以与不同类的集群资源管理器(Cluster Manager)进行通信,从而获得程序运 ...
- [轉]Linux kernel <2.6.29 exit_notify() local root exploit分析(2009-1337)
author : deep_pro目前网上的这个exploit(http://www.milw0rm.com/exploits/8369)的分析是有些问题的(http://forum.evilocta ...
- 项目中AOP的实例应用
其中包括了权限管理.表单验证.事务管理.信息过滤.拦截器.过滤器.页面转发等等. 公司项目的应用:(涉及用户验证登录以及用户是否有管理员权限.心理用户权限等),还有涉及的其他日志管理代码就不一一举例了 ...
- bzoj4550 小奇的博弈
我看出了是个 Nimk 问题.... dp我明白意思,我也会推组合数.... 但是...神tm统计答案啊...蒟蒻不会~