105. Construct Binary Tree from Preorder and Inorder Traversal

一、题目

  1、审题

  2、分析

    给出一个数值不重复的二叉树的先序、中序遍历的遍历顺序,求该二叉树的原始结构。

 

二、解答

  1、思路:

    分析二叉树的先序、中序遍历特点如下:

    ①、先序(preOrder): 根 --> 左 --> 右;

    ②、中序(inOrder):  左--> 根 --> 右;

    ③、先序的第一个节点为整颗二叉树的根节点(root),root 节点将中序序列分成两部分,root 左边的为 root 的左子树的所有子节点,root 右边的为 root 右子树的所有子节点;

    ④、先序的节点顺序在数组中正好是有序的;中序的节点顺序,若 index(node1) < index(node2),则 node2 为 node1 的祖先节点,或者为祖先节点的右孩子节点,或者为 node1的右孩子或其子孙节点;

 

    方法一、

      采用递归方法。

      ①、以 preOrder 首节点作为 root,则 root 在 inOrder 中出现的下标为 index,

        则 preOrder 的 (1,index)的节点即为 root 的左子树的先序遍历顺序, inOrder 的 (0, index - 1) 即为 root 的左子树的中序遍历的顺序,

        同理,preOrder 的 (index +1, len - 1) 为 root 的右子树的先序遍历顺序,inOrder 的 (index+1,len - 1)为 root 的右子树的中序遍历顺序。

      ②、递归的跳出条件为,root 在 preOrder 的下标 > preOrder 的数组最大下标,或 inOrder 的 left > right。

public TreeNode buildTree(int[] preorder, int[] inorder) {
        
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < inorder.length; i++) 
            map.put(inorder[i], i);
        return helper(0, 0, inorder.length - 1, preorder, inorder, map);
    }
    
    private TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder, Map<Integer, Integer> map) {
        
        // 跳出递归条件
        if(preStart > preorder.length - 1 || inStart > inEnd)
            return null;
        
        TreeNode root = new TreeNode(preorder[preStart]);
        int inIndex = map.get(root.val);
        root.left = helper(preStart+1, inStart, inIndex - 1, preorder, inorder, map);
        root.right = helper(preStart + (inIndex - inStart + 1), inIndex + 1, inEnd, preorder, inorder, map);
        
        return root;
    }

  

  方法二、

    创建一个 Stack, 以先序遍历顺序依次入栈,入栈时,判断该节点在 中序遍历中与站顶元素的位置关系:

      ①、若 中序遍历中栈顶元素排在此节点前, 则此节点必为站顶节点的左孩子。

      ②、若中序遍历中站顶元素在此节点后边,则站顶依次出栈,直到栈为空,或者站顶元素在中序遍历的位置排在此节点值的后边;

        此时,此节点必为前站顶元素的右孩子。

public TreeNode buildTree(int[] preorder, int[] inorder) {
       if(preorder.length == 0)
            return null;
        
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < inorder.length; i++) 
            map.put(inorder[i], i);
        
        Stack<TreeNode> stack = new Stack<>();
        int value = preorder[0];
        TreeNode root = new TreeNode(value);
        stack.push(root);
        
        for (int i = 1; i < preorder.length; i++) {
            value = preorder[i];
            TreeNode node = new TreeNode(value);
            
            if(map.get(value) < map.get(stack.peek().val)) {
                stack.peek().left = node;
            }
            else {
                TreeNode parent = null;
                while(!stack.isEmpty() && map.get(value) > map.get(stack.peek().val))
                    parent = stack.pop();    // stack 为空时跳出循环(即 node 为根节点右孩子),
                                            // 或者 stack 栈顶元素在 inorder 中顺序大于 node 跳出循环(即 node 为前站顶的右孩子)
                parent.right = node;
            }
            stack.push(node);
        }
        return root;
    }

 

      

 

posted @ 2018-09-30 22:46  skillking2  阅读(164)  评论(0编辑  收藏  举报