【剑指offer】7. 重建二叉树

剑指 Offer 07. 重建二叉树

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

   3
  /  \
 9   20
     / \
    15  7

限制:
0 <= 节点个数 <= 5000

解题思路

根据二叉树的前序遍历和中序遍历序列,还原二叉树,可用递归法和迭代法。其中,迭代法效率远高于递归法。

1. 递归

递归的方法非常直观。由于前序序列的第0个元素表示根节点,因此遍历中序序列,找到与前序序列第0个元素值相等的元素,即为根节点。在中序序例中,根节点左侧的序列值表示左子树,根节点右侧的序列值表示右子树。这样递归地切分前序序列和中序序列,分别找左子树和右子树即可。
要注意的是,Java中Arrays.copyOfRange(数组名,起始下标i,终止下标j),这个区间范围是[i, j),终止下标不包括在内。

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder==null || inorder==null || preorder.length<=0 || inorder.length<=0)
            return null;

        int len = preorder.length;
        TreeNode root = new TreeNode(preorder[0]);

        for(int i=0; i<len; i++){
            if(inorder[i]==preorder[0]){
                root.left = buildTree(Arrays.copyOfRange(preorder, 1, i+1), Arrays.copyOfRange(inorder, 0, i));
                root.right = buildTree(Arrays.copyOfRange(preorder, i+1, preorder.length), Arrays.copyOfRange(inorder, i+1, inorder.length));
            }
        }
        
        return root;
    }
}

2. 迭代

迭代法通过栈来存储遍历到的节点。对前序序列的节点进行遍历,初识时将中序序列的指针指向中序序列的第一个节点。每次判断前序序列的元素是否等于中序序列的元素,
(1)若不相等,则前序序列的元素为上一节点的左子节点,均入栈,直到当前遍历的前序元素值与当前的中序元素值相等(初始时中序序列的第一个元素是树的最左节点),说明达到树的最左节点。
(2)若前序序列的元素等于中序序列的元素,说明已遍历到树的最左节点,此时应反向遍历前序序列(即弹出栈定元素),同时中序序列的指针++(相当于正向遍历中序序列),直到栈为空或者找到上一个根节点元素。此时,当前节点(即从栈中弹出的最后一个节点)的右子节点是前序序列的当前节点,记录并入栈。
最后返回根节点(即前序序列第0个元素表示的节点)。

代码

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder==null || inorder==null || preorder.length<=0 || inorder.length<=0)
            return null;
        
        TreeNode root = new TreeNode(preorder[0]);
        int len = preorder.length;
        int inorderIndex = 0;

        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);

        for(int i=1; i<len; i++){
            TreeNode node = stack.peek();
            if(node.val != inorder[inorderIndex]){
                node.left = new TreeNode(preorder[i]);
                stack.push(node.left);
            }
            else{
                while(!stack.isEmpty() && stack.peek().val==inorder[inorderIndex]){
                    node = stack.pop();
                    inorderIndex++;
                }
                node.right = new TreeNode(preorder[i]);
                stack.push(node.right);
            }
        }

        return root;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值