给出一棵树的前序遍历和中序遍历,请构造这颗二叉树
注意:
可以假设树中不存在重复的节点
思路分析:
1.定义一个hash映射,便于定位根节点
2.遍历中序,定位中序节点位置
3.递归遍历左子树:先序遍历中「 从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
4.递归遍历右子树:先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param preorder int整型一维数组
* @param inorder int整型一维数组
* @return TreeNode类
*/
private Map<Integer,Integer> indexMap;
public TreeNode buildTree (int[] preorder, int[] inorder) {
int n=preorder.length;//前序中序节点个数都一样
indexMap=new HashMap<Integer, Integer>();//hashmap便于快速定位根节点
//记录中遍历节点的下标值及位置,方便寻找o(1)
for(int i=0;i<n;i++){
indexMap.put(inorder[i],i);
}
return mybuildTree(preorder,inorder,0,n-1,0,n-1);
}
public TreeNode mybuildTree(int[]preorder,int[]inorder,int preorder_left,int preorder_right,int inorder_left,int inorder_right){
if(preorder_left>preorder_right){
return null;
}
int preorder_root=preorder_left;//前序根节点
int inorder_root=indexMap.get(preorder[preorder_root]);//找出中序的根节点
//建立根节点
TreeNode node=new TreeNode(preorder[preorder_root]);
int left_size=inorder_root-inorder_left;//左子树节点的个数
//递归左子树,连接到根节点
node.left= mybuildTree(preorder,inorder,preorder_left+1,preorder_left+left_size,inorder_left,inorder_root-1);
//递归右子树,连接到根节点
node.right= mybuildTree(preorder,inorder,preorder_left+left_size+1,preorder_right,inorder_root+1,inorder_root);
return node;
}
}
给出一棵树的中序遍历和后序遍历,请构造这颗二叉树
注意:
保证给出的树中不存在重复的节点
位置关系的计算
在找到根节点位置以后,我们要确定下一轮中,左子树和右子树在中序数组和后续数组中的左右边界的位置。
左子树-中序数组 is = is, ie = ri - 1
左子树-后序数组 ps = ps, pe = ps + ri - is - 1 (pe计算过程解释,后续数组的起始位置加上左子树长度-1 就是后后序数组结束位置了,左子树的长度 = 根节点索引-左子树)
右子树-中序数组 is = ri + 1, ie = ie
右子树-后序数组 ps = ps + ri - is, pe - 1
解题思路:
1.定义一个hash映射,便于定位根节点
2.遍历中序,定位中序节点位置
3.调用mybuildTree(),递归左子树,递归右子树
import java.util.*;
class Solution {
HashMap<Integer,Integer> memo = new HashMap<>();
int[] post;
public TreeNode buildTree(int[] inorder, int[] postorder) {
for(int i = 0;i < inorder.length; i++) memo.put(inorder[i], i);
post = postorder;
TreeNode root = mybuildTree(0, inorder.length - 1, 0, post.length - 1);
return root;
}
public TreeNode mybuildTree(int is, int ie, int ps, int pe) {
if(ie < is || pe < ps) return null;
//后序遍历最后一位就是根节点
int root = post[pe];
//中序遍历中找到根节点的位置
int ri = memo.get(root);
//新建节点
TreeNode node = new TreeNode(root);
//递归左子树
node.left = mybuildTree(is, ri - 1, ps, ps + ri - is - 1);
//递归右子树
node.right = mybuildTree(ri + 1, ie, ps + ri - is, pe - 1);
return node;
}
}