一、题目
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如:前序遍历序列{ 1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8,6},重建二叉树并输出它的头结点。
二、解题思路
由前序遍历的第一个节点可知根节点。根据根节点,可以将中序遍历划分成左右子树。在前序遍历中找出对应的左右子树,其第一个节点便是根节点的左右子节点。按照上述方式递归便可重建二叉树。
public static class BinaryTreeNode {
int value;
BinaryTreeNode left;
BinaryTreeNode right;
}
public TreeNode rebuildBinaryTree(int preorder[], int inorder[]) {
// 输入的合法性判断,两个数组都不能为空,并且都有数据,而且数据的数目相同
if (preorder == null || inorder == null) {
return null;
}
TreeNode treeNode = rebuildBinaryTreeCore(preorder, 0, preorder.length - 1,
inorder, 0,inorder.length - 1);
return treeNode;
}
/**
* 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二节树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
*
* @param preorder 前序遍历
* @param startPreorder 前序遍历的开始位置
* @param endPreorder 前序遍历的结束位置
* @param inorder 中序遍历
* @param startInorder 中序遍历的开始位置
* @param endInorder 中序遍历的结束位置
* @return 树的根结点
*/
public TreeNode rebuildBinaryTreeCore(int preorder[], int startPreorder, int endPreorder,
int inorder[], int startInorder, int endInorder) {
// 开始位置大于结束位置说明已经没有需要处理的元素了
if (startPreorder > endPreorder || startInorder > endInorder) {
return null;
}
// 取前序遍历的第一个数字,就是当前的根结点
TreeNode root = new TreeNode(preorder[startPreorder]);
// 在中序遍历的数组中找根结点的位置
for (int i = startInorder; i <= endInorder; i++) {
if (preorder[startPreorder] == inorder[i]) {
// 其中(i - startInorder)为中序排序中左子树结点的个数
// 递归构建当前根结点的左子树,左子树的元素个数:index-startInorder+1个
// 左子树对应的前序遍历的位置在[startPreorder+1, startPreorder+index-startInorder]
// 左子树对应的中序遍历的位置在[startInorder, index-1]
root.left = rebuildBinaryTreeCore(preorder, startPreorder + 1,
startPreorder + (i - startInorder), inorder, startInorder, i - 1);
// 递归构建当前根结点的右子树,右子树的元素个数:endInorder-index个
// 右子树对应的前序遍历的位置在[startPreorder+index-startInorder+1, endPreorder]
// 右子树对应的中序遍历的位置在[index+1, endInorder]
root.right = rebuildBinaryTreeCore(preorder, startPreorder + (i - startInorder) + 1,
endPreorder, inorder, i + 1, endInorder);
}
}
return root;
}