输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
注明:
二叉树:
前序遍历:根节点 ->左子树 ->右子树
中序遍历:左子树 ->根节点 ->右子树
后序遍历:左子树 ->右子树 ->根节点
方法一:递归调用重建二叉树的方法,
以及调用JDK中的API方法Arrays.copyOfRange(int[],fromIndex,toIndex);
复制出数组中索引在区间[fromIndex,toIndex)中的元素
/**
* @author zhang
*
*输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
*假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
*例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列
{4,7,2,1,5,3,8,6},
*则重建二叉树并返回.
*
*二叉树:
*前序遍历:根节点 ->左子树 ->右子树
*中序遍历:左子树 ->根节点 ->右子树
*后序遍历:左子树 ->右子树 ->根节点
*例如:
* 树:a
* / \
* b c
* / \
* d f
* \ /
* e g
*
* 前序遍历:a b d e f g c
* 中序遍历:d e b g f a c
*
* 可以发现一个规律 前序遍历的第一个节点是根节点,
* 在中序遍历中根节点的两侧分别是根节点的左子树和右子树
* 可以通过该规律遍历递归重建二叉树
*
* 树的定义为:
*
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class BinaryTree {
//重建二叉树的方法
//pre前序遍历的数组 in中序遍历的数组
public TreeNode reConstructBinaryTree(int[] pre, int[] in){
if(pre.length==0 || in.length==0 || pre.length!=in.length){
return null;
}
//创建二叉树,并设置根节点
TreeNode tree = new TreeNode(pre[0]);
//遍历前序数组
for(int i=0;i<pre.length;i++){
if(pre[0] == in[i]){
//JDK的API函数Arrays.copyOfRange(int[],fromIndex,toIndex); 复制出数组中索引在区间[fromIndex,toIndex)中的元素
//递归调用reConstructBinaryTree()方法,根据根节点分别重建左子树和右子树
tree.left=reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+1),Arrays.copyOfRange(in, 0, i));
tree.right=reConstructBinaryTree(Arrays.copyOfRange(pre, i+1, pre.length),Arrays.copyOfRange(in,i+1, in.length));
}
}
return tree;
}
}
方法二:
/**
* 中心思想还是根据前面写的BinarySearch类中的实现方法进行,
* 唯一的区别就是不调用jdk的工具类中的Arrays.copyOfRange()了
* 自己定义一个类似的方法,来实现这个功能
*
*/
public class BinaryTree2 {
public TreeNode reConstructBinaryTree(int[] pre,int[] in){
if(pre.length==0||in.length==0||pre.length != in.length){
return null;
}
TreeNode tree = new TreeNode(pre[0]);
for(int i=0;i<pre.length;i++){
if(pre[0] == in[i]){
tree.left=reConstructBinaryTree(getChild(pre,1,i+1),getChild(in,0,i));
tree.right=reConstructBinaryTree(getChild(pre,i+1,pre.length),getChild(in,i+1,in.length));
}
}
return tree;
}
private int[] getChild(int[] array,int i,int j){
int length =j-i;
int[] newArray = new int[length];
for(int k=i,m=0;k<j;k++,m++){
newArray[m] = array[k];
}
return newArray;
}
}
回顾知识点:
二叉树有以下几个性质:TODO(上标和下标)
性质1:二叉树第i层上的结点数目最多为 2{i-1} (i≥1)。(2{k-1}是2的k-1次幂)
性质2:深度为k的二叉树至多有2{k}-1个结点(k≥1)。(2{k}是2的k次幂)
性质3:包含n个结点的二叉树的高度至少为log2 (n+1)。
性质4:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。
满二叉树(Full Binary Tree):
国内定义:
除最后一层无任何子节点外,每一层上的所有结点都有两个子结点二叉树。
国外定义:
a binary tree T is full if each node is either a leaf or possesses exactly two childnodes.
如果一个二叉树的节点要么是叶子节点(度为0),要么有两个子节点(度为2),那么该树就是满二叉树。
允许最后一层以外的其他层的节点没有子节点。
完全二叉树:
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
不允许最后一层的某个节点前缺少节点。