题目6:重建二叉树
题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出其二叉树并输出它的头结点。
解题思路:
在二叉树的前序遍历序列中, 第一个数字总是树的根节点的值,在中序遍历序列中, 根节点的值在序列的中间,左子树的节点值位于根节点的值的右边,因此需要中序遍历序列,才能找到根节点的值。
根据中序遍历在根节点左右子树出现的数字,可以找到左右子树子序列。因此在实现的时候,需要根据遍历序列和节点位置来实现
需要用一个构造函数constructor(int[] preOrder,int[] InOrder,int pStart,int pEnd,int iStart,int iEnd),其中preOrder和inOrder是前序遍历序列和中序遍历序列,pStart,pEnd表示输的前序遍历开始和结尾节点位置,iStart,iEnd表示中序遍历数组的开始和结束节点位置
代码实现
package swordToOffer;
public class Num6_ReconstructBinaryTree {
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val =val;
}
}
public static TreeNode ReconstructBinaryTree(int[] pre,int[] in) {
if(pre==null||in==null||pre.length<=0||in.length<=0||pre.length!=in.length) {
throw new RuntimeException("数组存在问题!");
}
return constructor(pre,in,0,pre.length-1,0,in.length-1);
}
public static TreeNode constructor(int[] preOrder,int[] inOrder,int pStart,int pEnd,int iStart,int iEnd) {
TreeNode root = new TreeNode(preOrder[pStart]);
if(pStart==pEnd&&iStart==iEnd) {
if(preOrder[pStart]!=inOrder[iStart]) {
throw new RuntimeException("数组存在问题!");
}
return root;
}
int index = iStart; //记录中序遍历序列中根节点位置
while(root.val!=inOrder[index]&&index<=iEnd) {
index++;
}
if(index>iEnd)
throw new RuntimeException("数组存在问题!");
int left = index-iStart;
//类似二分排序
if(left>0) {
root.left = constructor(preOrder,inOrder,pStart+1,pStart+left,iStart,index-1); //+1 是因为根节点为1 从1开始
}
if(left<iEnd-iStart) {
root.right = constructor(preOrder,inOrder,pStart+left+1,pEnd,index+1,iEnd);
}
return root;
}
public static void preOrder(TreeNode node) {
if(node==null) return ;
System.out.print(node.val);
preOrder(node.left);
preOrder(node.right);
}
public static void inOrder(TreeNode node) {
if(node==null) return;
inOrder(node.left);
System.out.print(node.val);
inOrder(node.right);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//正常二叉树
int[] pre = { 1, 2, 4, 7, 3, 5, 6, 8 };
int[] in = { 4, 7, 2, 1, 5, 3, 8, 6 };
TreeNode root = ReconstructBinaryTree(pre, in);
System.out.print("正常二叉树:");
preOrder(root);
System.out.print("||");
inOrder(root);
System.out.println();
//左斜树
int[] pre1 = { 1, 2, 3, 4, 5 };
int[] in1 = { 5, 4, 3, 2, 1 };
TreeNode root1 = ReconstructBinaryTree(pre1, in1);
System.out.print("左斜树:");
preOrder(root1);
System.out.print("||");
inOrder(root1);
System.out.println();
//右斜树
int[] pre2 = { 1, 2, 3, 4, 5 };
int[] in2 = { 5, 4, 3, 2, 1 };
TreeNode root2 = ReconstructBinaryTree(pre2, in2);
System.out.print("右斜树:");
preOrder(root2);
System.out.print("||");
inOrder(root2);
System.out.println();
//单个节点
int[] pre3 = { 2 };
int[] in3 = { 2};
TreeNode root3 = ReconstructBinaryTree(pre3, in3);
System.out.print("单个节点树:");
preOrder(root3);
System.out.print("||");
inOrder(root3);
System.out.println();
}
}
分析
- 对二叉树的前序、中序遍历的理解。通过不同的遍历划分出左右子树对应的子序列
- 分析复杂问题时,将二叉树的大问题分解为左右紫薯的问题,可以采用递归解决