第一个是正确的,而且考虑得很周到。
第二个不是。计算 fibs 的算法具有比 O(n^4) 高得多的时间复杂度(编辑:这是我写这个答案时被问到的——同时问题已经更新)。它甚至不是多项式。推理如下(符号#fib(x):调用fib计算fib(x)的次数):
- fib(1): #fib(1) = 1 (直接返回结果)
- fib(2): #fib(2) = 3(一个用于 fib(2),它调用它用于 fib(0) 和 fib(1))
- fib(3): #fib(3) = 5(一个用于 fib(3),它为 fib(2) 和 fib(1) 调用它,再给 3 + 1 个调用)
- fib(4): #fib(4) = 9
- fib(5): #fib(5) = 15
- fib(6): #fib(6) = 25
- ...
- fib(i): #fib(i) = 1 + #fib(i-1) + #fib(i-2)
所以你有了:
- #fib(i) ~= #fib(i-1) + #fib(i-2)
由此,可以合理地猜测计算 fib(i) 需要“大约”(实际上,略少于)2 倍于计算 fib(i-1) 的时间。因此,您可以“猜测” O(#fib(i)) = O(2^i)。这是正确的答案,您可以通过归纳轻松证明。
只是为了完成斐波那契数列,有更快的算法来计算第 n 个数。例如,具有线性时间(即 O(n))的算法是要记住您编写的那个函数(即,让它参考 Map 以检查它是否知道 n 的结果,所以立即返回它,否则,计算它,存储它并返回它)。还有一个封闭的公式来计算第 n 个 fib,因此是一个恒定时间算法(即 O(1))。
最后,O(n^4)算法的一个例子是任何有 4 个内部循环的东西,每个循环运行“大约”n 次。
例如,计算 n 边的 n 个立方体的体积(以非最优方式):
int volume = 0;
for (int cube = 0; cube < n; cube++)
for (int x = 0; x < n; x++)
for (int y = 0; y < n; y++)
for (int z = 0; z < n; z++)
volume++;
return volume;