根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
这道题和中序遍历与后续遍历构造树差不多,只是改一下子数组区间。
这次用了hashmap保存索引,比之前中序遍历与后续遍历构造树用的循环查询效率高了。
思路:
从前序数组可以知道,第一个节点为树的根节点。如果找到节点后,能将前序数组分为两个左右子数组[9]、[20,15,7] 那么左右子树的根节点分别为又是俩数组第一个位子的值。依次递归下去构建就可以构成树。
问题变为:如何将前序数组每次都能分隔成两个子数组,可以根据前序数组中的节点,在中序数组中位子去分割成左右子树(根节点左边为左子树,右边为右子树)。
例如: 前序中 索引 第一个(pre) 值为 3 在中序数组中找到索引为 1(mid),那么左子树个数为 1 - 0 = 1 个。 即 mid - inpre(中序第一索引)
那么开始切分前序数组,根据左子树大小来设立,左子树索引,[pre + 1,pre + mid - inpre] 右子树索引为[pre + mid + inpre + 1,preend] (preend为前序数组最后位子)
中序数组同样切分用于下次递归 继续切分数组
划分为 [instart,mid - 1] [mid + 1,inend]
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || preorder.length == 0) return null;
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i = 0; i < inorder.length; i++){//存储中序元素对应索引。
map.put(inorder[i],i);
}
return create(preorder,0,preorder.length - 1,inorder,0,inorder.length - 1,map);
}
public TreeNode create(int[] preorder,int prestart,int preend,int[] inorder, int instart, int inend,HashMap<Integer,Integer> map){
if(prestart > preend || instart > inend) return null;
int value = preorder[prestart]; //前序数组中第一个节点,左为构建本次树的根节点。
int mid = map.get(value); // 找到中序遍历中索引。
int num = mid - instart; //找到左子树节点个数,用于找在前序域中序遍历中到 左右子树数据区间
TreeNode root = new TreeNode(value);
root.left = create(preorder,prestart + 1, num + prestart,inorder,instart,mid - 1,map);
root.right = create(preorder,num + prestart + 1, preend,inorder,mid + 1,inend,map);
return root;
}
}