重建二叉树
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路
前序遍历顺序为根节点 -> 左子树 -> 右子树,中序遍历顺序为左子树 -> 根节点 -> 右子树。根据前序遍历以及中序遍历序列,重建树的根节点,并得到树的左右子树的前序与中序遍历序列。最后递归调用,重建左子树以及右子树。
代码
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre == null || pre.length == 0 || in == null || in.length ==0) {
return null;
}
// 在前序遍历序列中找到根节点的值,并重建根节点
int headValue = pre[0];
TreeNode headTreeNode = new TreeNode(headValue);
// 遍历中序序列,得到左子树节点数与右节点节点数
int leftSubTreeCount = 0;
int rightSubTreeCount = 0;
boolean isLeft = true;
for (int i = 0; i < in.length; i++) {
int currentValue = in[i];
if (currentValue == headValue) {
isLeft = false;
continue;
} else if(isLeft){
leftSubTreeCount++;
} else if(!isLeft) {
rightSubTreeCount++;
}
}
// 获得左右子树的前序以及中序遍历序列
int leftPreOffset = 1;
int leftInOffset = 0;
int[] leftPre = this.copyArray(pre, leftPreOffset, leftSubTreeCount);
int[] leftIn = this.copyArray(in, leftInOffset, leftSubTreeCount);
int rightPreOffset = 1 + leftSubTreeCount;
int rightInOffset = rightPreOffset;
int[] rightPre = this.copyArray(pre, rightPreOffset, rightSubTreeCount);
int[] rightIn = this.copyArray(in, rightInOffset, rightSubTreeCount);
// 递归调用,重建左右子树
TreeNode leftSubTreeNode = reConstructBinaryTree(leftPre, leftIn);
TreeNode rightSubTreeNode = reConstructBinaryTree(rightPre, rightIn);
// 根节点关联左右子树
headTreeNode.left = leftSubTreeNode;
headTreeNode.right = rightSubTreeNode;
return headTreeNode;
}
private int[] copyArray(int[] sourceArray, int offset, int count) {
int[] resultArray = new int[count];
for(int i = 0; i < count; i++) {
resultArray[i] = sourceArray[offset];
offset++;
}
return resultArray;
}
}
PREVIOUS剑指Offer 面试题05:从尾到头打印链表