• 105. Construct Binary Tree from Preorder and Inorder Traversal


    题目:

    Given preorder and inorder traversal of a tree, construct the binary tree.

    Note:
    You may assume that duplicates do not exist in the tree.

    链接: http://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

    题解:

    根据前序遍历和中序遍历重建二叉树,方法是自顶向下recursive来构建。前序就是 root -> left -> right,中序是 left -> root -> right。所以每次preorder[preLo]就是root。接下来preorder[preLo + 1]就是当前root的left child, 接下来在inorder中找到root的index  - rootAtInorder,则 inorder[rootAtInOrder + 1]就是当前root的right child。最后做递归的时候要注意,求left child时,inHi = rootAtInOrder - 1,求right child时, inLo = rootAtInOrder + 1。  应该还有不少更简便的方法,要好好想一想。

    Time Complexity - O(n), Space Complexity - O(n)。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            if(preorder == null || inorder == null || preorder.length != inorder.length || preorder.length == 0)
                return null;
            return buildTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);    
        }
        
        private TreeNode buildTree(int[] preorder, int preLo, int preHi, int[] inorder, int inLo, int inHi) {
            if(preLo > preHi || inLo > inHi)
                return null;
            TreeNode root = new TreeNode(preorder[preLo]);
            
            int rootAtInorder = 0;
            for(int i = inLo; i <= inHi; i++) {
                if(inorder[i] == root.val) {            //because no duplicate
                    rootAtInorder = i;
                    break;
                }                  
            }
            
            int leftSubTreeLen = rootAtInorder - inLo;
            root.left = buildTree(preorder, preLo + 1, preLo + leftSubTreeLen, inorder, inLo, rootAtInorder - 1);
            root.right = buildTree(preorder, preLo + leftSubTreeLen + 1, preHi, inorder, rootAtInorder + 1, inHi);
            return root;
        }
    }

    Discussion里还有一些很好的写法, 比如使用一个stack进行iterative重建;或者不做辅助函数,使用arrays.copyof,把原array分割后分别递归计算left child和right child。

    要多思考多练习。

    PS: 今天 Twitter裁员 8%, 好吓人。

    二刷:

    方法和一刷一样,就是使用递归来重建树。找到根节点以后,求出左子树长度和右子树长度,然后分别递归调用辅助方法求出左child和右child,最后返回root就可以了。各种边界要想得细一点。

    可以使用HashMap保存inorder的key, value,这样在递归调用辅助方法时可以O(1)拿到rootVal,就不用顺序搜索了。 (下一道题也是一样)

    Java:

    Time Complexity - O(n), Space Complexity - O(n)。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public TreeNode buildTree(int[] preorder, int[] inorder) {
            if (preorder == null || inorder == null || preorder.length != inorder.length || preorder.length == 0) return null;
            return buildTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
        }
        
        private TreeNode buildTree(int[] preorder, int preLo, int preHi, int[] inorder, int inLo, int inHi) {
            if (preLo > preHi || inLo > inHi) return null;
            int rootVal = preorder[preLo];
            TreeNode root = new TreeNode(rootVal);
            int rootIndexAtInorder = inLo;
            while (rootIndexAtInorder <= inHi) {
                if (inorder[rootIndexAtInorder] == rootVal) break;
                rootIndexAtInorder++;
            }
            int leftTreeLen = rootIndexAtInorder - inLo;
            root.left = buildTree(preorder, preLo + 1, preLo + leftTreeLen, inorder, inLo, rootIndexAtInorder - 1);
            root.right = buildTree(preorder, preLo + leftTreeLen + 1, preHi, inorder, rootIndexAtInorder + 1, inHi);
            return root;
        }
    }

    Reference:

    https://leetcode.com/discuss/63586/neat-java-solution-pretty-easy-to-read

    https://leetcode.com/discuss/2297/the-iterative-solution-is-easier-than-you-think

    https://leetcode.com/discuss/28271/my-o-n-19ms-solution-without-recusion-hope-help-you

    https://leetcode.com/discuss/18101/sharing-my-straightforward-recursive-solution

    https://leetcode.com/discuss/12179/my-accepted-java-solution

    https://leetcode.com/discuss/32414/recursive-solution-in-java

  • 相关阅读:
    Docker常用命令总结(不断更新)
    Docker容器简介-与虚拟机的区别及安装步骤
    ELK搭建—安装使用Kibana可视化
    使用CURL与ElasticSearch服务进行通信
    安装部署ElasticSearch单节点在Linux服务器上
    ElasticStack分布式引擎技术栈(ELK)介绍
    为Nginx服务器配置黑(白)名单的防火墙
    php大力力 [026节] php开发状态要随时做好整理工作
    php大力力 [025节] 来不及学习和分类的,大力力认为有价值的一些技术文章合集(大力力二叔公)(2015-08-27)
    php大力力 [024节]PHP中的字符串连接操作(2015-08-27)
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4437296.html
Copyright © 2020-2023  润新知