1. 题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
2. 思路
前序遍历的形式:
根节点, [左子树的前序遍历结果], [右子树的前序遍历结果]
中序遍历的形式:
[左子树的中序遍历结果], 根节点, [右子树的中序遍历结果]
(1)由前序遍历可以得到根节点,根据根节点索引和中序遍历结果,我们就可以分别知道左子树和右子树中的节点数目。可以通过哈希索引标记中序遍历结果。
(2)根据前序遍历的结果,对上述形式中的所有左右括号进行定位,递归构造出左子树和右子树,再将这两颗子树接到根节点的左右位置。
(3)在递归地遍历某个子树的过程,将这颗子树看成一颗全新的树,按照上述的顺序进行遍历。
3. 代码
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
//全局变量:用于标记中序遍历
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
//全局变量:前序遍历
int[] preorder;
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
//标记中序遍历
for(int i=0;i<inorder.length;i++){
map.put(inorder[i],i);
}
return travel(0,0,inorder.length-1);
}
/**
* 递归构造二叉树
* @param root 先序遍历索引
* @param in_left 当前树的左边界
* @param in_right 当前树的右边界
*/
public TreeNode travel(int root,int in_left,int in_right){
//递归终止条件:越过叶子结点
if(in_left>in_right)
return null;
//按照先序遍历的规则:根节点->左子树->右子树,获得根节点
TreeNode node = new TreeNode(preorder[root]);
int index = map.get(preorder[root]);
//左子树的根节点=前序遍历根节点的下一个
node.left = travel(root+1,in_left,index-1);
//右子树根节点=(中序根节点索引-中序左边界)+先序根节点索引+1,其中括号内=左子树长度。
node.right = travel((index-in_left)+root+1,index+1,in_right);
return node;
}