一、题目
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
示例 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]
限制:0 <= 节点个数 <= 5000
二、思路
首先通过遍历找到根节点、进而确定该根节点的左右子树,再分别确定左、右子树的根节点。依次递归。当根节点没有左右子树的时,结束递归。
画图找一下规律:
1、前序遍历的第一个节点是根节点、进而将中序遍历结果分为两份左右两颗树,得到根节点是3;
2、再由左子树的前序遍历结果(9)确定左子树的根节点为9,
右子树的前序遍历结果(20、15、7),得到右子树的根节点为20;
3、由中序遍历结果:此时根节点为9的左子树已经没有左右子树。根节点为20的右子树再分为两部分:左子树15、右子树7;
4、依次递归,直至根节点没有左右子树。
三、代码
// 全局哈希表,
HashMap<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
// 判断是否为空
if(preorder==null||preorder.length<=0){
return null;
}
for (int i = 0; i < inorder.length; i++) {
// 给中序遍历做映射
map.put(inorder[i],i);
}
TreeNode root = f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
return root;
}
TreeNode f(int[] preorder ,int l1,int r1,int[] intorder,int l2,int r2){
// 递归出口
if(l1>r1&&l2>r2){
return null;
}
// 获取根节点:前序遍历的第一个节点
TreeNode root = new TreeNode(preorder[l1]);
// 获取根节点的下标
int i =map.get(preorder[l1]);
// 递归处理左子树
root.left =f(preorder,l1+1,l1+(i-l2),intorder,l2,i-1);
// 递归处理右子树
root.right=f(preorder,l1+(i-l2)+1,r1,intorder,i+1,r2);
return root;
}
运行结果:
四、总结
二叉树前序遍历:先遍历根节点、再遍历左子树、最后遍历右子树。(根左右)
二叉树中序遍历:先遍历左子树、再遍历根节点、最后遍历右子树。(左根右)
二叉树后序遍历:先遍历左子树、再遍历右子树、最后遍历根节点。(左右根)
三种遍历的递归代码只需要调整代码的顺序即可。迭代代码需要用到辅助栈。