Fibonacci的时间复杂度为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)
有人可以告诉为什么会这样吗?
根据他的说法,这是因为我们在每一步都要调用两次Fibonacci函数,这就是为什么它是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(n)相同,尽管函数在每一步都调用两次。
有人可以告诉我,我们中间谁错了,实际的逻辑是什么?
答案 0 :(得分:3)
这个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”等之前完成......)
答案 1 :(得分:3)
实际上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语句更改为:
,这可以简单地转换为O(n)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,{{1对于k-2,(k-1)(k-2)
表示k-3,等等。
所以看起来像(k-1)(k-2)(k-3)
。
如果您要通过O((k-1)!)
,则i
要求k,1
要求k-1,1
要求k-2,{{ 1}}表示k-3,1+1=2
表示k-4,1+1+2=4
表示k-5等。
所以看起来像1+1+2+4=8
。
二叉树遍历需要16
,但O(2^(k-1))
不是二叉树的高度,而是节点的数量。在Fibonacci示例中,O(n)
是高度。如果我们考虑根据高度遍历平衡二叉树需要多长时间,我们最终得到n
,从一些基本数学开始,最终为n
。