整体思想为:
先通过先序找到中序中root的位置,
再通过中序root的位置找到左子树的区间,和右子树的区间
递归左右子树
当穿过叶子结点结束
public class Offer07 {
/** 先通过先序找到中序中root的位置,
* 再通过中序root的位置找到左子树的区间,和右子树的区间
* 递归左右子树
*
* 当穿过叶子结点结束
* */
private HashMap<Integer,Integer> map;
private int[] preorder;
public TreeNode buildTree(int[] preorder, int[] inorder) {
/** 将中序遍历的数组存入map中,方便根据结点的值查找到对应索引*/
this.map = new HashMap<Integer, Integer>();
int idx = 0;
for (int i :
inorder) {
map.put(i, idx++);
}
this.preorder = preorder;
/** 调用递归*/
return helper(0,0,preorder.length-1);
}
/** 创建执行递归的函数 传入先序的root结点的索引,和中序的区间的左右边界索引 返回子树*/
public TreeNode helper(int pre_root_idx, int in_left_idx, int in_right_idx){
/** 终止条件: 区间大小为0*/
if (in_left_idx > in_right_idx) return null;
/** 问题与子问题之间的关系为:
* root.left = helper(先序的左子树root结点的索引,中序左子树的区间索引,当前结点)
* root.right = helper(先序的右子树root结点的索引,中序右子树的区间索引,当前结点)
* return root;*/
TreeNode root = new TreeNode(preorder[pre_root_idx]);//建根节点,也就是先序遍历的第一个元素
// 左子树 先序root结点索引+1 中序left 中序root结点的索引-1
root.left = helper(pre_root_idx+1,in_left_idx,map.get(preorder[pre_root_idx])-1);
// 右子树 先序root结点+左子树的长度 中序root结点+1 中序右边界
root.right = helper(pre_root_idx + (map.get(preorder[pre_root_idx]) - in_left_idx + 1),map.get(preorder[pre_root_idx])+1,in_right_idx);
return root;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}