zoukankan      html  css  js  c++  java
  • 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;
        }

          

  • 相关阅读:
    某不知名的树形Dp
    HDU-5963 朋友 思维
    CF1292C Xenon's Attack on the Gangs
    Emergency Evacuation 模拟了一下
    NOI2003 逃学的小孩
    UVA11300 Spreading the Wealth 数学
    ACWing 1510 楼梯
    测试代码高亮
    Pollard-rho的质因数分解
    米勒罗宾素数检测(Miller-Rabin)
  • 原文地址:https://www.cnblogs.com/skillking/p/9733626.html
Copyright © 2011-2022 走看看