剑指--重建二叉树

剑指–重建二叉树

1,题目:

在这里插入图片描述
2,思路:

递归解析:

  • 1.递推参数: 前序遍历中根节点的索引pre_root、中序遍历左边界in_left、中序遍历右边界in_right。
  • 2.终止条件: 当 in_left > in_right ,子树中序遍历为空,说明已经越过叶子节点,此时返回 null 。
  • 3.递推工作:
  • 4.建立根节点root: 值为前序遍历中索引为pre_root的节点值。
  • 5.搜索根节点root在中序遍历的索引i: 为了提升搜索效率,本题解使用哈希表 dic 预存储中序遍历的值与索引的映射关系,每次搜索的时间复杂度为 O(1)。
  • 6.构建根节点root的左子树和右子树: 通过调用 recur() 方法开启下一层递归。
  • 7.左子树: 根节点索引为 pre_root + 1 ,中序遍历的左右边界分别为 in_left 和 i - 1。
  • 8.右子树: 根节点索引为 i - in_left + pre_root + 1(即:根节点索引 + 左子树长度 + 1),中序遍历的左右边界分别为 i + 1 和 in_right。
  • 9.返回值: 返回 root,含义是当前递归层级建立的根节点 root 为上一递归层级的根节点的左或右子节点。

下面是对应的图解:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法二:迭代法:

1.使用前序遍历的第一个元素创建根节点。
2.创建一个栈,将根节点压入栈内。
3.初始化中序遍历下标为 0。
4.遍历前序遍历的每个元素,判断其上一个元素(即栈顶元素)是否等于中序遍历下标指向的元素。
5.若上一个元素不等于中序遍历下标指向的元素,则将当前元素作为其上一个元素的左子节点,并将当前元素压入栈内。
6.若上一个元素等于中序遍历下标指向的元素,则从栈内弹出一个元素,同时令中序遍历下标指向下一个元素,之后继续判断栈顶元素是否等于中序遍历下标指向的元素,若相等则重复该操作,直至栈为空或者元素不相等。然后令当前元素为最后一个想等元素的右节点。
7.遍历结束,返回根节点。

3,代码:

递归法:

class Solution {
    /*
    递归解析:
1.递推参数: 前序遍历中根节点的索引pre_root、中序遍历左边界in_left、中序遍历右边界in_right。
2.终止条件: 当 in_left > in_right ,子树中序遍历为空,说明已经越过叶子节点,此时返回 null 。
3.递推工作:
4.建立根节点root: 值为前序遍历中索引为pre_root的节点值。
5.搜索根节点root在中序遍历的索引i: 为了提升搜索效率,本题解使用哈希表 dic 预存储中序遍历的值与索引的映射关系,每次搜索的时间复杂度为 O(1)。
6.构建根节点root的左子树和右子树: 通过调用 recur() 方法开启下一层递归。
7.左子树: 根节点索引为 pre_root + 1 ,中序遍历的左右边界分别为 in_left 和 i - 1。
8.右子树: 根节点索引为 i - in_left + pre_root + 1(即:根节点索引 + 左子树长度 + 1),中序遍历的左右边界分别为 i + 1 和 in_right。
9.返回值: 返回 root,含义是当前递归层级建立的根节点 root 为上一递归层级的根节点的左或右子节点。


    */
    HashMap<Integer, Integer> dic = new HashMap<>();
    int[] po;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        po = preorder;
        for(int i = 0; i < inorder.length; i++) 
            dic.put(inorder[i], i);
        return recur(0, 0, inorder.length - 1);
    }
    TreeNode recur(int pre_root, int in_left, int in_right) {
        if(in_left > in_right) return null;
        TreeNode root = new TreeNode(po[pre_root]);//建立根节点root: 值为前序遍历中索引为pre_root的节点值。
        int i = dic.get(po[pre_root]);
        root.left = recur(pre_root + 1, in_left, i - 1);//左子树: 根节点索引为 pre_root + 1 ,中序遍历的左右边界分别为 in_left 和 i - 1。
        root.right = recur(pre_root + i - in_left + 1, i + 1, in_right);//右子树: 根节点索引为 i - in_left + pre_root + 1(即:根节点索引 + 左子树长度 + 1),中序遍历的左右边界分别为 i + 1 和 in_right。
        return root;
    }
}

方法二:迭代法:

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        //迭代

        /*
        1.使用前序遍历的第一个元素创建根节点。
2.创建一个栈,将根节点压入栈内。
3.初始化中序遍历下标为 0。
4.遍历前序遍历的每个元素,判断其上一个元素(即栈顶元素)是否等于中序遍历下标指向的元素。
5.若上一个元素不等于中序遍历下标指向的元素,则将当前元素作为其上一个元素的左子节点,并将当前元素压入栈内。
6.若上一个元素等于中序遍历下标指向的元素,则从栈内弹出一个元素,同时令中序遍历下标指向下一个元素,之后继续判断栈顶元素是否等于中序遍历下标指向的元素,若相等则重复该操作,直至栈为空或者元素不相等。然后令当前元素为最后一个想等元素的右节点。
7.遍历结束,返回根节点。


        */
        if (preorder == null || preorder.length == 0) {
            return null;
        }
        TreeNode root = new TreeNode(preorder[0]);
        int length = preorder.length;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        int inorderIndex = 0;
        for (int i = 1; i < length; i++) {//遍历前序遍历的每个元素,判断其上一个元素(即栈顶元素)是否等于中序遍历下标指向的元素。
            int preorderVal = preorder[i];
            TreeNode node = stack.peek();
            if (node.val != inorder[inorderIndex]) {
                node.left = new TreeNode(preorderVal);
                stack.push(node.left);
            } else {
                while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
                    node = stack.pop();
                    inorderIndex++;
                }
                node.right = new TreeNode(preorderVal);
                stack.push(node.right);
            }
        }
        return root;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值