二叉树平等的空间/时间复杂性

时间:2014-04-18 14:06:05

标签: algorithm complexity-theory

我昨天接受了一次采访,其中涉及一个非常基本的树数据结构:

t ::= int | (t * t)

其中tTree是整数(叶)或两个t,表示左右子树。这意味着树在叶级别具有值。

示例树可能如下所示:

         t 
      /     \ 
     t        t
   /   \    /   \
  1     2  3     4

任务是编写一个函数equal(t, t) => bool,它需要两个tTrees并确定它们是否相等,非常简单。

我编写了相当标准的代码,结果如下(下面是伪代码):

fun equal(a, b) {
   if a == b {   // same memory address
      return true
   } 

   if !a || !b { 
      return false
   }

   // both leaves 
   if isLeaf(a) && isLeaf(b) {
      return a == b 
   }

   // both tTrees
   if isTree(a) && isTree(b) {
      return equal(a->leftTree, b->leftTree) 
          && equal(a->rightTree, b->rightTree)
   }

   // otherwise
   return false
}

当被要求给出时间和空间的复杂性时,我很快回答:

O(n) time 
O(1) space

我的采访者声称他们可以创建一个树,这样这个相同的功能将在O(2^n)指数时间内运行。鉴于上述算法,我没有(现在仍然没有)看到这是可能的。我看到该函数以递归方式调用自身两次,但每次调用的输入大小都减半了吗?因为你只是并行检查各个子树。

对此的任何想法或意见都会非常有帮助。

1 个答案:

答案 0 :(得分:1)

目前,你的代码是O(n),而你的面试官也错了。代码在空间使用时不是O(1):在最坏的情况下(当树非常不平衡时)它是O(n),因为你的代码是递归的(而不是尾递归)。 / p>

可能他们要求你写一个测试两棵树是否同构的函数。也就是说,他们期望你编写在比较这两棵树时返回true的代码:

  *      *
 / \    / \
1   2  2   1

然后他们误解了你的解决方案,假设你写了这样做的天真代码,那就是O(2 ^ n)。

另一种可能性是某些指针可以在同一棵树的左右分支中重复使用,允许具有2 ^ n个节点的树在O(n)空间中表示。那么如果' n'是内存中结构的大小,而不是节点的数量,那么访调员的立场是正确的。这是一棵树:

  ___   ___   ___   ___   ___
 /   \ /   \ /   \ /   \ /   \
*     *     *     *     *     1
 \___/ \___/ \___/ \___/ \___/

根位于左侧,它有32个叶节点(全部为1)。