【问题标题】:construct a binary tree from in-order and level-order traversal从中序和水平序遍历构造二叉树
【发布时间】:2013-02-13 15:36:50
【问题描述】:

首先,我想说这不是家庭作业。我正在准备面试并遇到这个问题。我想我们可以通过 in-order 和 level-order 遍历的定义。 :-)。

例如:

      50
   /      \
 10        60
/  \       /  \
5   20    55    70
        /     /  \
      51     65    80

上述树的中序和层序遍历分别是:

5、10、20、50、51、55、60、65、70、80

50、10、60、5、20、55、70、51、65、80

我的想法:

(1)遍历层序数组找出第一个元素 它出现在有序数组中。我们称这个元素为当前元素 根。

(2) 在有序数组中找到当前根的索引。有序的 数组由索引分隔。有序数组的左边 是当前根的左子树和右子树 有序数组是当前根的右子树。

(3) 将有序数组更新为其左侧,然后转到步骤 1。

(4) 将有序数组更新为其右侧,然后转到步骤 2。

以上面的树为例。

(1) 5 is the first element appears in the in-order array. 

(2) [50 ...60] is the left sub-tree of 5 and [20 ... 80] is the right sub-tree of 5. 

(3) update the in-order array as [50 ... 60]

    (1) 10 is the first element appears in [50 10 60].

    (2) [50] is the left sub-tree of 10 and [60] is the right sub-tree of 10.

    (3) update ...

谁能帮我验证我的解决方案? 如果再给我一个,真的很感激。

【问题讨论】:

  • 我认为这不符合规定,according to Wikipedia。
  • 我刚刚写了一个程序来验证它。中序遍历似乎没有问题。能否请您按顺序遍历示例树让我仔细检查一下?
  • 看来我弄错了。看起来是对的,抱歉。

标签: data-structures binary-tree inorder


【解决方案1】:

我认为你在正确的轨道上。以下是我使用您的数据制定的工作代码。

/*
//construct a bst using inorder & levelorder traversals.
//inorder    - 5, 10, 20, 50, 51, 55, 60, 65, 70, 80
//levelorder - 50, 10, 60, 5, 20, 55, 70, 51, 65, 80
         50
      /      \
    10        60
   /  \       /  \
  5   20    55    70
            /     /  \
          51     65    80
 */
struct node *construct_bst3(int inorder[], int levelorder[], int in_start, int in_end)
{
    static int levelindex = 0;
    struct node *nnode = create_node(levelorder[levelindex++]);

    if (in_start == in_end)
        return nnode;

    //else find the index of this node in inorder array. left of it is left subtree, right of this index is right.
    int in_index = search_arr(inorder, in_start, in_end, nnode->data);

    //using in_index from inorder array, constructing left & right subtrees.
    nnode->left  = construct_bst3(inorder, levelorder, in_start, in_index-1);
    nnode->right = construct_bst3(inorder, levelorder, in_index+1, in_end);

    return nnode;
}

【讨论】:

  • 这个算法的时间和空间复杂度是多少? O(n)?
  • @AnV 不可能是 O(n)。这将是 O(logn) 的某个因素。
  • 我们需要为数组中的所有N个元素创建节点,然后在返回时将它们附加到它们的父节点。所以我认为 TC 将是 O(n)。你能解释一下它是如何成为 O(logn) 的因素的吗?
  • @AnV 对不起!不知道我在写上述评论时在想什么。上述方法的时间复杂度上限为 O(n3)。我们在搜索中进行线性扫描,然后是左右子树。如果我们可以在 search_Arr 中使用查找表,我们可以得到 O(n2)
【解决方案2】:

其实思路很简单,只需要确定遍历顺序是否正确即可。比如你想做中序遍历,你可以简单的这么想:从左到右,从下到上。

  1. 遍历同一个节点的左下角(5),然后再遍历右下角(20)。

  2. 从底部(10)遍历到顶部(50)。

  3. 在左边做同样的事情。

对于杠杆顺序,你可以从上到下,从左到右,一步一步地遍历。

【讨论】:

    【解决方案3】:
                static tree MakeTreeFromInorderAndLevelOrder(int[] inorder,int[] lorder,int s,int n,int cnt1) {
        if(s>n || s>=inorder.length || n>=inorder.length || cnt1>=inorder.length) {
            return null;
        }
        int mIndex = Search(lorder[cnt1],inorder,s,n);
        tree t = new tree(lorder[cnt1]);
    
        cnt1 = 2*cnt1 + 1;
        t.left = MakeTreeFromInorderAndLevelOrder(inorder,lorder,s,mIndex-1,cnt1);
        //Boundary case
        if(cnt1<inorder.length && t.left==null) {
            t.right =   MakeTreeFromInorderAndLevelOrder(inorder,lorder,mIndex+1,n,cnt1);
        }
        else {
        cnt1 -=1;
        cnt1 /=2;
        cnt1 = 2*cnt1 + 2;
        t.right = MakeTreeFromInorderAndLevelOrder(inorder,lorder,mIndex+1,n,cnt1);
        //Boundary case
        if(t.right ==null && cnt1<inorder.length) {
            t.left = MakeTreeFromInorderAndLevelOrder(inorder,lorder,s,mIndex-1,cnt1);
        }
        }
        return t;
    }
    

    【讨论】:

    • 您好,欢迎来到stackoverflow!但是,我不明白这是如何回答这个问题的。发帖人问是否有人可以验证他的算法的正确性,而不是用于实现。如果您认为您的实现以某种方式提供了此验证,请在您的答案中解释这一点。另外,请确保您的答案格式正确且易于阅读。
    【解决方案4】:
        node *construct (in, s, e, level) 
        {
          while (level order has element)
          {
              make the root by taking the first element from level order
              find the index of root->Val in in order.
    
              segregate the elements of left subtree and right subtree (make sure while 
              segregating from level order the order of element should be same)  call them
              leftLevel[] and rightLevel[]
    
              construct tree by recursively calling
              root->left  = construct(inorder,s, index-1, leftLevel);
              root->right = construct(inorder, index+1, e, rightlevel);
              return root;
          }
     }
    

    元素的分离需要 O(n) 使用哈希表,因此在平衡树中整体复杂度将是 O(nlogn),但当树不平衡时它将达到 O(n^2)。

    【讨论】:

      猜你喜欢
      • 2021-09-03
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多