Algorithm 递归模式的大O时间复杂度

Algorithm 递归模式的大O时间复杂度,algorithm,recursion,time-complexity,big-o,Algorithm,Recursion,Time Complexity,Big O,我对递归模式的运行时有疑问 示例1 int f(int n) { if(n <= 1) { return 1; } return f(n - 1) + f(n - 1); } 我读到上面代码的运行时是O(2^logn),因为它是平衡的,但我仍然认为它是O(2^N)。有人能解释一下吗 当元素的数量每次减半时,运行时是logn。但是二叉树在这里是如何工作的呢 它是2^logn,仅仅因为它是平衡的吗 如果不平衡怎么办 编辑: 我们可以解O(2^logn)=O(N),但我认

我对递归模式的运行时有疑问

示例1

int f(int n) {
  if(n <= 1) {
    return 1;
  }

  return f(n - 1) + f(n - 1);
}
我读到上面代码的运行时是O(2^logn),因为它是平衡的,但我仍然认为它是O(2^N)。有人能解释一下吗

  • 当元素的数量每次减半时,运行时是logn。但是二叉树在这里是如何工作的呢
  • 它是2^logn,仅仅因为它是平衡的吗
  • 如果不平衡怎么办
  • 编辑: 我们可以解O(2^logn)=O(N),但我认为它是O(2^N)


    谢谢

    我要试试看

    在平衡二叉树中,每个父节点的左侧和右侧各有一半子节点。树的第一层是根,有1个元素,下一层有2个元素,下一层有4个元素,然后是8个元素,依此类推。因此,对于具有L层的树,树中有
    2^L-1
    节点

    与此相反,如果您有N个元素要插入到树中,那么最终将得到一个深度为
    L=log_2(N)
    的平衡二叉树,因此您只需要调用
    log_2(N)
    层的递归算法。在每一层中,对算法的调用数量都是原来的两倍,因此在您的情况下,您最终会得到
    2^log\u 2(N)
    调用和
    O(2^log\u 2(N))
    运行时。请注意,
    2^log_2(N)=N
    ,因此这两种方法都是相同的,但我们将在一秒钟内利用二叉树的优势

    如果树不平衡,则最终深度大于
    log_2(N)
    ,因此有更多的递归调用。在极端情况下,当您的所有子对象都位于其父对象的左侧(或右侧)时,您有N个递归调用,但每个调用都会立即从其一个分支返回(一侧没有子对象)。因此,您将有
    O(N)
    运行时,这与以前相同。每个节点访问一次

    平衡树的一个优点是在类似搜索的情况下。如果左边的子节点总是小于父节点,而右边的子节点总是大于,则可以在
    O(log_2(n))
    time(而不是
    2^log_2(n)
    )中的
    n
    节点中搜索元素
    n
    )。但是,如果您的树严重不平衡,则此搜索将成为所有值的线性遍历,并且您的搜索是
    O(N)
    。如果
    N
    非常大,或者您执行了大量的搜索,这可能是易处理算法和难处理算法之间的区别。

    • 二叉树与这里的任何其他树一样具有复杂性
      O(n)
      ,因为您最终要遍历树的所有元素。通过减半,我们没有做任何特殊的事情,除了分别计算相应孩子的总和

    • 这个术语是这样来的,因为如果它是平衡的,那么
      2^(log_2(n))
      是树中元素的数量(叶+非叶)。(
      log2(n)
      levels)

    • 同样,如果它不平衡,那也没关系。我们正在做一个需要考虑每个元素的操作,使运行时成为
      O(n)


    这在哪里有意义?如果它正在搜索一个元素,那么它就很重要(不管它是否平衡)

    只是澄清一下:2^(logn)与N是相同的,所以O(2^ logn)可能与O(N)是相同的。这个特殊的函数是O(N),无论它是否平衡,因为如果不访问所有N个节点来读取所有N个值,就无法对所有N个值求和。在这个问题中,不管你是否使用二叉树,你都要访问每个节点一次,所以你的复杂度是O(N)。它是O(2^N),其中N是深度。它是O(2^logn),其中N是节点数。N是一个变量,问题中没有N,因此可以假设它是任何东西-可能任何人告诉你它是O(2^N)只是做出了一个与你不同的假设(或者可能他们只是错了)。这个
    sum
    函数不是
    O(2^logn)
    –它是
    O(N)
    谢谢你的解释:)
    int sum(Node node) {
      if(node == null) {
        return 0;
      }
    
      return sum(node.left) + node.value + sum(node.right);
    }