从中序与后序遍历序列构造二叉树
中序遍历顺序为:左子节点、根结点、右子节点。
后序遍历顺序为:左子节点、右子节点、根结点。
首先,从二叉树的中序遍历和后序遍历的流程可知,后序遍历数组的最后一个元素代表的即为根节点。知道这个性质后,我们可以利用已知的根节点信息在中序遍历的数组中找到根节点所在的下标,然后根据其将中序遍历的数组分成左右两部分,左边部分即左子树,右边部分为右子树,针对每个部分可以用同样的方法继续递归下去构造。
大致的思路知道了,下面说一下具体的实现:
1.为了高效查找根节点元素在中序遍历数组中的下标,我们可以创建一个哈希表来存储中序序列,即建立一个(元素,下标)键值对的哈希表。
2.定义一个int类型的rootIndex表示(后序序列中)当前遍历的根结点的位置。
3.定义递归函数 dfs(in_left, in_right) 表示当前递归到的(中序序列中的)子树的左右边界,主函数中只需调用dfs(0, len - 1) 即可。对于递归函数的内部:
①如果 in_left > in_right,说明子树为空,返回null。
②从后序遍历数组中选择当前根结点,即使用postorder[rootIndex]的值构造根节点。
③利用哈希表查询当根节点在中序遍历中的下标 index。那么从 in_left 到 index - 1 属于左子树,从 index + 1 到 in_right 属于右子树。
④根据后序遍历逻辑,递归创建右子树 dfs(index + 1, in_right) 和左子树 dfs(in_left, index - 1)。
注意:这里必须先创建右子树,再创建左子树。因为在后序遍历的数组中是先存储左子树的节点,再存储右子树的节点,最后存储根节点,如果按每次选择「后序遍历的最后一个节点」为根节点,则先被构造出来的应该为右子树。
⑤返回根节点 root。
代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
HashMap<Integer,Integer>map=new HashMap<>();
int rootIndex;
public TreeNode buildTree(int[] inorder, int[] postorder) {
int len=