【Leetcode】Construct Binary Tree From Inorder and Preorder/Postorder Traversal

38 篇文章 0 订阅
15 篇文章 0 订阅

【题目】

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

【思路】

Hint:
A good way to attempt this question is to work backwards. Approach this question by drawing a binary tree, then list down its preorder and inorder traversal. As most binary tree problems, you want to solve this recursively.

About Duplicates:
In this solution, we will assume that duplicates are not allowed in the binary tree. Why?

Consider the following case:

preorder = {7, 7}
inorder = {7, 7}

We can construct the following trees which are both perfectly valid solutions.

  7                     7
 /           or          \
7                         7

Clearly, there would be ambiguity in constructing the tree if duplicates were allowed.


Solution:
Let us look at this example tree.

        _______7______
       /              \
    __10__          ___2
   /      \        /
   4       3      _8
            \    /
             1  11

The preorder and inorder traversals for the binary tree above is:

preorder = {7,10,4,3,1,2,8,11}
inorder = {4,10,3,1,7,11,8,2}

The crucial observation to this problem is the tree’s root always coincides with the first element in preorder traversal. This must be true because in preorder traversal you always traverse the root node before its children. The root node’s value appear to be 7 from the binary tree above.

We easily find that 7 appears as the 4th index in the inorder sequence. (Notice that earlier we assumed that duplicates are not allowed in the tree, so there would be no ambiguity). For inorder traversal, we visit the left subtree first, then root node, and followed by the right subtree. Therefore, all elements left of 7 must be in the left subtree and all elements to the right must be in the right subtree.

We see a clear recursive pattern from the above observation. After creating the root node (7), we construct its left and right subtree from inorder traversal of {41031} and {1182} respectively. We also need its corresponding preorder traversal which could be found in a similar fashion. If you remember, preorder traversal follows the sequence of root node, left subtree and followed by right subtree. Therefore, the left and right subtree’s postorder traversal must be {10431} and {2811} respectively. Since the left and right subtree are binary trees in their own right, we can solve recursively!

public TreeNode buildTree(int[] preorder, int[] inorder) {
    return helper(0, 0, inorder.length - 1, preorder, inorder);
}

public TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder) {
    if (preStart > preorder.length - 1 || inStart > inEnd) {
        return null;
    }
    TreeNode root = new TreeNode(preorder[preStart]);
    int inIndex = 0; // Index of current root in inorder
    for (int i = inStart; i <= inEnd; i++) {
        if (inorder[i] == root.val) {
            inIndex = i;
        }
    }
    root.left = helper(preStart + 1, inStart, inIndex - 1, preorder, inorder);
    root.right = helper(preStart + inIndex - inStart + 1, inIndex + 1, inEnd, preorder, inorder);
    return root;
}

We left out some details on hoTw we search the root value’s index in the inorder sequence. How about a simple  linear search? If we assume that the constructed binary tree is always balanced, then we can guarantee the run time complexity to be O( N log  N), where  N is the number of nodes. However, this is not necessarily the case and the constructed binary tree can be skewed to the left/right, which has the worst complexity of O( N 2).

A more efficient way is to eliminate the search by using an efficient look-up mechanism such as hash table. By hashing an element’s value to its corresponding index in the inorder sequence, we can do look-ups in constant time. Now, we need only O(N) time to construct the tree, which theoretically is the most efficient way.

The basic idea is here: Say we have 2 arrays, PRE and IN. Preorder traversing implies that PRE[0] is the root node. Then we can find this PRE[0] in IN, say it's IN[5]. Now we know that IN[5] is root, so we know that IN[0] - IN[4] is on the left side, IN[6] to the end is on the right side. Recursively doing this on subarrays, we can build a tree out of it :)


【代码】


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值