Ox00 结论
个人认为,严格意义上的时间复杂度应为:
0x01 引言
最近学习数据结构,书中将递归实现的Fibonacci数列的时间复杂度一笔带过,称Fibonacci数列的时间复杂度为O(2^n),在网上查了查O(2^n)的由来。但在知乎上又看到有人将Fibonacci数列的时间复杂度算出来是。这里进行讨论。个人想法,有问题希望大家多多包含,并指出问题所在。
0x02 递归代码
- C代码
#include <stdio.h>
long fib(int n)
{
if(n==0 || n==1)
return 1;
return fib(n-1) + fib(n-2);
}
int main()
{
int i;
for(i=0; i<10; i++)
{
printf("%d\n", fib(i));
}
return 0;
}
- 运行
0x03 时间复杂度
- 说法一
如上图,要想得到
fib(6)需要先计算fib(5)和fib(4); 想要的到fib(5)需要先计算fib(4)和fib(3);以此类推。将红色框内的fib(2)和fib(1)移动到上一次最右侧,则上一层共 。这样作为计算,很容易得到时间复杂度为 。
- 说法二
fib(1)和fib(2)的个数并不能直接用 进行粗略的计算。记fib(6)为第1层,则fib(1)为第6层,fib(2)为第5层。显然,fib(1)和fib(3)的个数是相同的。所以fib(1)和fib(2)的总个数为fib(4)+fib(5)=3+5=8。而又fib(4)+fib(5)=fib(6)=fib(n),所以fib(1)和fib(2)的总个数为fib(n)。根据斐波那契数列的通项公式得出:通过求同阶方程,最终得出时间复杂度为 。
- 分析(求解)
-
f(n)fib(n)的语句频度等于递归过程中fib(1)和fib(2)总的执行次数。所以,求解递归算法的时间复杂度相当于递归方程求解。
对于斐波那契数列
当
n>=2时有f(n)=f(n-1)+f(n-2)当
n=0或n=1有f(n)=1递归方程求解,也就是求斐波那契数列的通项公式。
-
"O"求与
Fn同阶的函数。算法中同阶指的是,当n->∞时,两个函数之比的结果是一个非0的常数,则称这两个函数是同阶的。-
如果时间复杂度是。相比求极限,结果为
0 -
如果时间复杂度是。相比求极限,结果为
-
-
ret: 斐波那契数列的通向公式函数与是同阶的。
- 另一种思路
设
fib(n)的执行时间为T(n), 则fib(n-1)的执行时间为T(n-1),fib(n-2)的执行时间为T(n-2)。语句 if(n==0 || n==1) return 1; 的执行时间为O(1)。if判断语句相对于return语句的时间可以忽略。所以。
当
n=1或n=2时,fib函数执行return 1,执行时间为。综上:
递归方程求解,得出
fib(n)执行时间为:
当
n->∞再化简,可以得到时间复杂度为。
0x04 个人想法
其中数学符号“O”的严格定义为:
若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n)=O(f(n))表示存在正的常数C和n0,使得当n>=n0时都满足0<=T(n)<=Cf(n)。
所以,从严格意义上来讲,也是不对的。
其中 的正负与n的奇偶相关,所以f(n)是波动的,不可能存在C,使得当n>=n0时都满足0<=T(n)<=Cf(n)。
综上,严格意义上,时间复杂度应为:
0x05 总结
通过分析(非严格意义上),斐波那契数列递归形式的时间复杂度更应该为。
那 又是怎么回事?
-
首先,前面举例的
fib(6)通过 算出来的结果和通过 算出来的结果相同,纯属偶合。当n不为6时,显然是不相同的,方程都不同。 -
两个时间复杂度的共同点是,都是指数阶。因为是指数阶的代表,所以使用作为递归求解斐波那契数列的时间复杂度,也可能只是想表明它是指数阶。
-
一般指数阶的算法根本不考虑使用,所以知道这是个指数阶的时间复杂就ok了,研究它的时间复杂度具体是什么也是没有必要的。并且(渐进)时间复杂度本来就不是机器执行算法的真实时间。
两个时间复杂度的函数图像