关闭

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

标签: leetcodeconstructtreepreorderinorder
5844人阅读 评论(0) 收藏 举报
分类:

转载请注明出处: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~~

1
0
查看评论

LeetCode 105:Construct Binary Tree from Preorder and Inorder Traversal

LeetCode 105: Given preorder and inorder traversal of a tree, construct the binary tree. 给定一个二叉树的前序和中序遍历,重建这棵二叉树。
  • sunao2002002
  • sunao2002002
  • 2015-05-20 23:09
  • 1037

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

【106-Construct Binary Tree from Preorder and Inorder Traversal(通过前序和中序遍历构造二叉树)】【LeetCode-面试算法经典-Java实现】【所有题目目录索引】原题  Given preorder and inorder traver...
  • DERRANTCM
  • DERRANTCM
  • 2015-08-09 06:37
  • 2488

[JAVA]LeetCode105 Construct Binary Tree from Preorder and Inorder Traversal

根据前序遍历和中序遍历,构建二叉树。假设树中不存在相同的节点
  • fumier
  • fumier
  • 2015-03-29 10:39
  • 735

C++详解Leetcode:105. Construct Binary Tree from Preorder and Inorder Traversal

原题思路通过二叉树的前序遍历和中序遍历来构建二叉树,通过递归可以很容易的解决这个问题,在遇到二叉树的问题,应该习惯先画图再来解决code/** * Definition for a binary tree node. * struct TreeNode { * int val; * ...
  • u014265347
  • u014265347
  • 2017-07-30 17:34
  • 297

Construct Binary Tree from Preorder and Inorder Traversal -- LeetCode

原题链接: http://oj.leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/  这道题是树中比较有难度的题目,需要根据先序遍历和中序遍历来构造出树来。这道题看似毫...
  • linhuanmars
  • linhuanmars
  • 2014-04-24 08:43
  • 17415

LeetCode Construct Binary Tree from Preorder and Inorder Traversal

通过一棵二叉树的前序和中序排列来得出它的树形结构。
  • u013291394
  • u013291394
  • 2016-02-17 09:18
  • 917

leetcode笔记:Construct Binary Tree from Preorder and Inorder Traversal

这道题考察了先序和中序遍历,先序是先访问根节点,然后访问左子树,最后访问右子树;中序遍历是先遍历左子树,然后访问根节点,最后访问右子树。
  • liyuefeilong
  • liyuefeilong
  • 2015-11-30 23:54
  • 1304

[LeetCode-21]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.
  • sbitswc
  • sbitswc
  • 2014-05-21 05:59
  • 3777

leetCode练习(105)

题目:Construct Binary Tree from Preorder and Inorder Traversal           难度:medium 问题描述: Given pr...
  • u010771890
  • u010771890
  • 2016-10-29 14:55
  • 401

面试笔试杂项积累-leetcode 101-105

101.101-Symmetric Tree-Difficulty: Easy Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For example...
  • wolf96
  • wolf96
  • 2016-02-04 23:02
  • 578
    个人资料
    • 访问:1292794次
    • 积分:9492
    • 等级:
    • 排名:第2256名
    • 原创:182篇
    • 转载:9篇
    • 译文:2篇
    • 评论:797条
    联系方式
    博客专栏
    最新评论
    CNZZ统计