前提:二叉树中无重复元素
思路:前序遍历结果的第一个节点为树的根节点,后面是根节点的左子树与右子树的所有节点 比如preorder = [3,9,20,15,7],3就是树的根节点 而中序遍历的则是在根节点前输出根节点的左子树的全部节点,在根节点后输出根节点的右子树的所有节点 inorder = [9,3,15,20,7],所以可以在这个数组中找到3为根节点,即9为左子树的所有节点,15,20,7为右子树所有系欸但 确定了右子树,在前序遍历preorder数组中,20在最前面,因此20为右子树的根节点,所以15为左子节点,7为右子节点 即树为 3 9 20 15 7 所以可以按照这个规律来对树进行构造
代码:
public static Map<Integer,Integer> map=new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
/*
前序遍历结果的第一个节点为树的根节点,后面是根节点的左子树与右子树的所有节点
比如preorder = [3,9,20,15,7],3就是树的根节点
而中序遍历的则是在根节点前输出根节点的左子树的全部节点,在根节点后输出根节点的右子树的所有节点
inorder = [9,3,15,20,7],所以可以在这个数组中找到3为根节点,即9为左子树的所有节点,15,20,7为右子树所有系欸但
确定了右子树,在前序遍历preorder数组中,20在最前面,因此20为右子树的根节点,所以15为左子节点,7为右子节点
即树为 3
9 20
15 7
所以可以按照这个规律来对树进行构造
*/
int n=preorder.length;
if(n==1)
return new TreeNode(preorder[0]);
//因为树中不存在重复元素,所以可以使用哈希映射
for(int i=0;i<n;i++){
map.put(inorder[i],i);
}
return dfs(preorder,inorder,0,n-1,0,n-1);
}
public TreeNode dfs(int[] p,int[] d,int pleft,int pright,int dleft,int dright){
if(pleft>pright)
return null;
//确认根节点
int val=p[pleft];
//在中序遍历数组中找到根节点所在位置
int index=map.get(val);
//构造根节点
TreeNode root=new TreeNode(val);
//确认左子树的节点数
int sum=index-dleft;
//递归左子树
root.left=dfs(p,d,pleft+1,pleft+sum,dleft,index-1);
//递归右子树
root.right=dfs(p,d,pleft+sum+1,pright,index+1,dright);
return root;
}
容易踩的坑:
1、递归左右子树时,边界条件设置错误,最好画图或者按照案例模拟一遍,否则传参时,索引容易超边界.
2、不要忘记设置递归结束条件.
如果不加上前提:二叉树中无重复元素这一条件,则如果根节点元素与其他节点元素值相同时,则在寻找根节点时需要额外消耗时间.无法使查找根节点位置这一操作达到O(1)时间复杂度.