【问题标题】:Exponential Time complexity指数时间复杂度
【发布时间】:2014-03-21 15:27:13
【问题描述】:

斐波那契的时间复杂度是O(2^n) 如果我想获得 3^n 的时间复杂度怎么办?

根据我朋友的说法,斐波那契的时间复杂度是 O(2^n),这是由于以下步骤:-

return fibonacci(n-1)+fibonacci(n-2)

另外他说如果我们写的话,它会变成O(3^n):-

return fibonacci(n-1)+fibonacci(n-2)+fibonacci(n-3)

有人能说出为什么会这样吗?

据他说,这是因为我们在每一步都调用了两次斐波那契函数,这就是为什么它是 O(2^n)。如果是这样,那么以下代码的复杂度应该是 O(k^k) 但据我所知它是 O(n)

void permute(int k,int size) {  
    // some base case    
    for (i=k-1;i>=0;i--)          
    permute(k-1,size);  
    return; 
}

他的逻辑在我看来是垃圾。对我来说,由于合并成本,它是 2^n。 尽管函数在每一步调用自身两次,但二叉树遍历成本也是如此。

谁能告诉我我们当中谁错了,实际逻辑是什么?

【问题讨论】:

  • 算法具有复杂性。斐波那契只是一个序列。
  • 是的,我知道,谢谢
  • 那你应该已经意识到像“斐波那契的时间复杂度是 O(2^n)”这样的句子没有意义。你只能说“以下实现的复杂性是……”
  • 下次我会处理的。现在你能回答这个问题吗?虽然问的不正确,但我想你已经明白我想问的了。
  • 通过使用什么逻辑你得出 permute 是 O(n)?

标签: algorithm time-complexity fibonacci


【解决方案1】:

实际上 O(2^n) 有点过冲(但仍然正确,因为 big-O 是一个上限),it's more like ~θ(1.6^n)

试着描绘一棵递归树。每个节点都分裂成2,树的深度是n,所以最终结果大约是O(2^n)。

同理,O(3^n)的例子,每个节点分裂成3个,深度还是n。

但是对于 O(3^n),我宁愿推荐这样的东西:

someFunction(n)
  if (n == 0)
    return 1
  return someFunction(n-1) + someFunction(n-1) + someFunction(n-1)

当然,这可以通过将最后一个 return 语句更改为:

return 3*someFunction(n-1)

但这并不是重点(也可以在 O(n) 中计算第 n 个斐波那契数)。

现在很容易评估。

n 有 1 个调用,n-1 有 3 个调用,n-2 有 3*3,n-3 有 3*3*3 等等。

运行时间为 O(3^n)。


对于permute 函数:

由于您将k-1 传递给递归调用(不是i),因此您有1 调用k,k-1 用于k-1,(k-1)(k-2) 用于k-2,(k-1)(k-2)(k-3)对于 k-3 等。

所以看起来像O((k-1)!)


如果您改为传递i,您将有1 调用k,1 用于k-1,1+1=2 用于k-2,1+1+2=4 用于k-3,@987654337 @ 代表 k-4,16 代表 k-5,等等。

所以看起来像O(2^(k-1))


二叉树遍历需要O(n),但n不是二叉树的高度,而是节点的数量。在斐波那契示例中,n 是高度。如果我们要根据高度来考虑遍历平衡二叉树需要多长时间,我们也会得到O(2^height),从一些基础数学来看,它最终是O(n)

【讨论】:

  • 那为什么算法遍历二叉树的复杂度是O(n)而不是O(2^n)?
【解决方案2】:

这个previous answer 应该让你了解斐波那契数列算法的时间复杂度。

那么,基于同样的答案原则,你的新序列算法可以表示为

T(n) 
= T(n-1) + T(n-2) + T(n-3) 
= ( T(n-2)+T(n-3)+T(n-4) )+( T(n-3)+T(n-4)+T(n-5) )+( T(n-4)+T(n-5)+T(n-6) )
= ...

您会看到每个节点创建了 3 个新节点。那算法复杂度变成O(3^n)

来自 Wolfram 的图像:(考虑节点 13 到 37 在下面继续,因为树的底部不是“平坦的”,因为第一级“n-3”节点将在“n-2”之前完成,在“n-1”之前完成,等等...)

【讨论】:

  • 那为什么遍历二叉树的算法复杂度是O(n)而不是O(2^n)?
  • 遍历一个由n个个节点组成的二叉树的复杂度是O(n)。遍历类似于 Fibonacci 生成的树的复杂度,即更像 ~2^n,显然是 O(2^n)。
  • 这个答案根本没有回答问题,而且图表似乎没有帮助。
  • 因为你的斐波那契算法不使用记忆,它计算相同的值不止一次,而树遍历只访问每个节点一次。
  • @ring0 The complexity to traverse a tree similar to the one generated by Fibonacci, ie more like ~2^n is obviously O(2^n) 这取决于你叫什么n。您调用fibonacci()时使用的节点数或参数。
猜你喜欢
  • 2019-06-13
  • 1970-01-01
  • 2016-02-13
  • 2012-08-14
  • 2017-04-12
  • 1970-01-01
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多