重建二叉树java实现
剑指Offer面试题——七
题目描述:输入某个二叉树的前序遍历和中序遍历结果,重建该二叉树.。例如输入前序遍历[1,2,4,7,3,5,6,8] 和中序遍历[4,7,2,1,5,3,8,6]则重建如下图的二叉树
1
/ \
2 3
/ / \
4 5 6
\ /
7 8
1.思路图解
首先我们来看一下二叉树的遍历,所有前序遍历的第一个元素,一定是该二叉树的根节点。但是在中序遍历中根节点是在中间的,所以根据这两个特点,可以在中序遍历的数组中扫描,直到找到前序遍历中的根节点,这样就可以将中序遍历的数组分为三个部分。
如上图所示,前序遍历中第一个数1就是根节点,然后再中序遍历中扫描直到找到1为止,根据中序遍历(左根右)的特点,1前面的三个数[2,4,7] 就是左子树的节点的值,1后面的四个数[5,3,8,6]就是右子树节点的值
这时就找到了第一个根节点1
1
/ \
[2,4,7] [5,3,8,6]
然后这时就以前序遍历片段[2,4,7] 和 中序遍历片段[4,7,2] 重复完成上述过程
1
/ \
2 [5,3,8,6]
/
[4,7]
2.代码实现
package datasturct;
public class ConstructCore {
public static void main(String[] args) {
int[] pre = {1, 2, 4, 7, 3, 5, 6, 8};
int[] infix = {4, 7, 2, 1, 5, 3, 8, 6};
TreeNode construct = construct(pre, infix);
System.out.println(construct);
}
private static TreeNode construct(int[] pre, int[] infix) {
if (pre == null || infix == null) {
return null;
}
return constructTree(pre, infix, 0, pre.length - 1, 0, infix.length - 1);
}
/**
* @param pre 前序便利数组
* @param infix 中序遍历数组
* @param preStart 递归时使用pre前序遍历数组开始的地方
* @param preEnd 递归时使用pre前序遍历数组结束的地方
* @param infixStart 递归时使用infix中序遍历数组开始的地方
* @param infixEnd 递归时使用infix中序遍历数组开始的地方
* @return 返回重建二叉树之后的根节点
*/
public static TreeNode constructTree(int[] pre, int[] infix, int preStart, int preEnd, int infixStart, int infixEnd) {
//前序遍历中,第一个值就为根节点
int rootVal = pre[preStart];
TreeNode root = new TreeNode(rootVal);
if (preStart == preEnd) {
if (infixStart == infixEnd && pre[preStart] == infix[infixStart]) {
return root;
}
}
int rootInfix = infixStart;
//通过while循环找到rootVal在中序遍历数组infix中的位置
while (rootInfix <= infixEnd && infix[rootInfix] != rootVal) {
rootInfix++;
}
//如果到最后还没有找到
if (rootInfix == infixEnd && infix[rootInfix] != rootVal) {
System.out.println("Invalid Input");
}
int leftLength = rootInfix - infixStart; //左子树长度 应该为 根节点索引 - 中序遍历数组开始的位置
int leftPreEnd = preStart + leftLength; // 下一次向左递归 前序遍历数组结束的位置 应该为前序遍历数组开始的位置
if (leftLength > 0) {
//向左递归构建左子树
root.setLeft(constructTree(pre, infix, preStart + 1, leftPreEnd, infixStart, rootInfix - 1));
}
if (leftLength < preEnd - preStart) {
root.setRight(constructTree(pre, infix, leftPreEnd + 1, preEnd, rootInfix + 1, infixEnd));
}
return root;
}
}
class TreeNode {
private int value;
private TreeNode left;
private TreeNode right;
public TreeNode(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public TreeNode getLeft() {
return left;
}
public void setLeft(TreeNode left) {
this.left = left;
}
public TreeNode getRight() {
return right;
}
public void setRight(TreeNode right) {
this.right = right;
}
@Override
public String toString() {
return "TreeNode{" +
"value=" + value +
'}';
}
public void preOrder() {
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
}
if (this.right != null) {
this.right.preOrder();
}
}
public void infixOrder() {
if (this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if (this.right != null) {
this.right.infixOrder();
}
}
}