剑指 Offer 07. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
限制:
0 <= 节点个数 <= 5000
来源:力扣(LeetCode)
链接:(https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/
思路:题目中给你了前序遍历 和中序遍历的数组。
前序遍历性质: 节点按照 [ 根节点 | 左子树 | 右子树 ] 排序。
中序遍历性质: 节点按照 [ 左子树 | 根节点 | 右子树 ] 排序。
以题目示例为例:
前序遍历划分 [ 3 | 9 | 20 15 7 ]
中序遍历划分 [ 9 | 3 | 15 20 7 ]
由此可以看出:前序遍历的第一个元素就是根节点,我们可以根据根节点在中序遍历中的索引,将中序遍历划分为:[ 9 | 根节点 | 15 20 7 ]
通过以上三步:可以确定 1.树的根节点、2.左子树根节点、3.右子树根节点。
递推参数: 根节点在前序遍历的索引 root 、子树在中序遍历的左边界 left 、子树**在中序遍历的右边界 right **;
终止条件: 当 left > right ,代表已经越过叶节点,此时返回 nullnull ;
直接上代码吧 代码中有解释!
解题:
int[] pre;
HashMap<Integer,Integer> map=new HashMap<>();
public TreeNode buildTree(int[] preorder,int[] inorder){
this.pre=preorder;
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i],i);
}
return dfs(0,0,inorder.length-1);
}
//参数 rootIndex 根节点在前序数组中的索引 left中序遍历的左边界 right中序遍历的右边界
public TreeNode dfs(int rootIndex,int left,int right){
if (left>right) return null;
TreeNode node=new TreeNode(pre[rootIndex]);
int i=map.get(pre[rootIndex]);//i 是根节点在中序遍历的索引
// 重建左子树 递归左子树
node.left=dfs(rootIndex+1,left,i-1);
// 重建右子树 递归右子树 i-left是左子树的长度 rootIndex是根节点的索引
node.right=dfs(rootIndex+i-left+1,i+1,right);
return node;
}
这道题还是有难度的!代码容易写!题解难写啊!