【LeetCode】105. Construct Binary Tree from Preorder and Inorder Traversal 解题报告

原创 2016年06月01日 23:42:08

转载请注明出处:http://blog.csdn.net/crazy1235/article/details/51559645


Subject

出处:https://leetcode.com/problems/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.


Explain

给定一个二叉树的先序遍历中序遍历,构造出一颗二叉树。

二叉树的遍历分为先序遍历、中序遍历、后序遍历、层序遍历。

而通过先序遍历和中序遍历、中序遍历和后序遍历 是可以还原该二叉树结构的。


Solution

solution 1

递归方式

     4
   /   \
  2     7
 / \   / \
1   3 6   9

以上面的二叉树为例。
其先序遍历结果是:【4 2 1 3 7 6 9】
中序遍历结果是:【1 2 3 4 6 7 9】

对先序遍历来说:

先序遍历的每个值表示的结点都是接下来的若干结点的父结点。

比如【4】是这个二叉树的根结点。
【2】是【1 3】的父结点。
【1】是 空的父结点,也即使叶子结点。

对中序遍历来说:

根结点一定在中间位置,中间左边是左子树,右边是右子树。
比如【4】左边是【1 2 3】是根结点的左子树,右边是【6 7 9】是根结点的右子树。
对于【2】来说,【1】是其左子树,【3】是其右子树。
……
依次类推。

很明显,这是一个递归过程。

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

        if (preorder.length != inorder.length) {
            return null;
        }

        return build(preorder, inorder, 0, 0, inorder.length - 1);
    }
public TreeNode build(int[] preorder, int[] inorder, int preIndex,
            int startInIndex, int endInIndex) {
        if (endInIndex < startInIndex) {
            return null;
        }
        TreeNode node = new TreeNode(preorder[preIndex]);

        // the index of current node in inorder
        int index = getIndexInInorder(inorder, preorder[preIndex]);
        int lenL = index - startInIndex;
        int lenR = endInIndex - startInIndex - lenL;

        if (lenL > 0) {
            node.left = build(preorder, inorder, preIndex + 1, startInIndex,
                    index - 1);
        }
        if (lenR > 0) {
            node.right = build(preorder, inorder, preIndex + lenL + 1,
                    index + 1, endInIndex);
        }

        return node;
    }
//获得val值在inorder中的下标
public int getIndexInInorder(int[] inorder, int val) {
        for (int i = 0; i < inorder.length; i++) {
            if (val == inorder[i]) {
                return i;
            }
        }
        return -1;
    }

build( ) 是主要递归方法。

因为参数是两个int数组。需要指定preorder数组的下标,还需要指定当前递归中中序对应的若干结点,用 startInIndexendInIndex 分别表示开始和结束下标。


LeetCode平台测试通过之后,发现build方法可以稍微优化一些。如下:

public TreeNode build2(int[] preorder, int[] inorder, int preIndex,
            int startInIndex, int endInIndex) {
        if (endInIndex < startInIndex) {
            return null;
        }
        int currentVal = preorder[preIndex];
        TreeNode node = new TreeNode(currentVal);

        // the index of current node in inorder
        int index;
        for (index = startInIndex; index <= endInIndex; index++) {
            if (currentVal == inorder[index]) {
                break;
            }
        }
        // int lenL = index - startInIndex;
        // int lenR = endInIndex - index;

        if (index > startInIndex) {
            node.left = build(preorder, inorder, preIndex + 1, startInIndex,
                    index - 1);
        }
        if (endInIndex > index) {
            node.right = build(preorder, inorder, preIndex + index
                    - startInIndex + 1, index + 1, endInIndex);
        }

        return node;
    }

优化之前,RunTime 是 :8ms
beats 73.81% of java submissions.

但是问题来了:“优化之后”,在LeetCode平台测试,发现效率竟然还慢了不知为何???


solution 2

方法二是在【Discuss】频道看到的答案。
使用的是非递归方式。

    /**
     * 
     * @param preorder
     * @param inorder
     * @return
     */
    public TreeNode buildTree2(int[] preorder, int[] inorder) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            map.put(inorder[i], i);
        }
        TreeNode root = null;
        TreeNode p = root;
        Stack<TreeNode> stack = new Stack<>();
        for (int i = 0; i < preorder.length; i++) {
            int temp = map.get(preorder[i]);
            TreeNode node = new TreeNode(preorder[i]);
            if (stack.isEmpty()) {
                root = node;
//              stack.add(node);
                p = root;
            } else {
                if (temp < map.get(stack.peek().val)) {
                    p.left = node;
                    p = p.left;
                } else {
                    while (!stack.isEmpty() && temp > map.get(stack.peek().val)) {
                        p = stack.pop();
                    }
                    p.right = node;
                    p = p.right;
                }
            }
            stack.add(node);
        }

        return root;
    }

该方法的RunTime是 9ms
beats 73.29% of java submissions.

比我的方法稍微慢一点点,哈哈~


bingo~~

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

【LeetCode-面试算法经典-Java实现】【105-Construct Binary Tree from Preorder and Inorder Traversal(构造二叉树)】

【106-Construct Binary Tree from Preorder and Inorder Traversal(通过前序和中序遍历构造二叉树)】【LeetCode-面试算法经典-Java...

PAT - 甲级 - 1110. Complete Binary Tree (25) (判断完全二叉树+建树)

题目描述: Given a tree, you are supposed to tell if it is a complete binary tree. Input Specification: ...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

SCRT连接到虚拟机ubuntu

SSH看做是telnet的加强版,telnet的密码和信息都是不加密的,而ssh则加密。  想用SecureCRT连接Linux--Ubuntu,需要SSH服务的支持,很多Linux系统在安装的...

PAT - 甲级 - 1020. Tree Traversals (25)(层次遍历)

题目描述: Suppose that all the keys in a binary tree are distinct positive integers. Given the postorde...

浅析dev目录下设备文件mknod节点gid,uid和mode的如何方便设置

init=> handle_device_fd 收到uevent信息=> handle_device_event=>static void handle_device_event(struct u...

UVa - 536 - Tree Recovery(给定中序和先序求后序,递归)

思路:由先序遍历可得到根节点。在中序遍历中找到根节点的位置,然后分别递归左子树和右子树,一般的思路到这里是递归建树,但是由于是要求后序遍历的序列。是左孩子+右孩子+根节点,而递归建树时是通过找到根节点...

LeetCode 105:Construct Binary Tree from Preorder and Inorder Traversal

LeetCode 105: Given preorder and inorder traversal of a tree, construct the binary tree. 给定一个二叉树的...

【华为OJ】【107-24点运算】

【华为OJ】【算法总篇章】【华为OJ】【107-24点运算】【工程下载】题目描述计算24点是一种扑克牌益智游戏,随机抽出4张扑克牌,通过加(+),减(-),乘(*), 除(/)四种运算法则计算得到整数...

卡尔曼滤波器学习笔记(一)

Kalman Filter学习笔记(一) 卡尔曼滤波器的原理及应用最近在学习Probablistic Robotics这本书,获益良多。以前学了概率论和随机过程之后一直觉得这些是...

Construct Binary Tree from Preorder and Inorder Traversal -- LeetCode

原题链接: http://oj.leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/  这...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)