是否知道计算第n个Fibonacci序列的最快Java算法是什么?
我找到了these algorithms。我猜迭代算法应该比递归和分析算法更快。
答案 0 :(得分:4)
将所有Fibonacci数预先计算到n的足够大的数量,并生成一个源代码片段,用于定义一个数组,该数组的类型可以包含这些数字。
然后,您只需检索数组中索引n
中的值即可。这是O(1)
。比这快得多。
答案 1 :(得分:2)
试试dynamic programming。创建一个包含第n-1个Fibonacci数的每个值的数组。第一次运行时,它需要与普通的Fibonacci函数一样长,但后续调用可以在O(1)中运行,因为你已经拥有了数组中的值。
答案 2 :(得分:2)
根据我的经验,分析版本在实践中通常非常快,但正如Rosetta代码所说,它只能在序列中的第92个数字上准确。
递归版本需要指数时间才能运行,因此即使对于中等大小的 n ,它也必然非常慢。迭代和尾递归函数在 n 中需要时间线性。可以从Fibonacci序列的matrix form推导出更快的O(lg n )时间算法。
有关递归和尾递归算法的解释,请参阅SICP。
答案 3 :(得分:2)
答案是,像往常一样,“它取决于”。一般来说,你不能真正存储那么多Fibonacci数字,因为它们往往会相当快速地增加 - 事实上,你的链接的分析部分会以指数方式显示它们。
因此,对于大多数实际目的,答案是“不计算 - 缓存”。也就是说,使用查找表。 (通常,在溢出之前,您需要少于100个条目。)
对于传统的存储方法,你不会比递归计算更好,因为它是O(d ^ 2),其中d是输出的位数 - 更复杂的任意大小的数字操作将很难与之竞争。
“分析”可能是较慢的方法之一,因为基础不方便,你将扔掉快速整数数学。
答案 4 :(得分:2)
虽然你确实特别针对Java,但我昨晚在Python 3中看到了不同的实现。特别是,我查看了天真的递归实现和分析实现(然而我称之为封闭形式)。这是代码,没有我的单元测试:
import math
from timeit import Timer
def fib_recursive(n):
"""
Compute the Fibonacci sequence from a given number n
"""
if n < 2:
return n
else:
return fib_recursive(n - 2) + fib_recursive(n - 1)
def fib_closed_form(n):
"""
Compute the Fibonacci sequence using a closed form.
"""
def calc_golden_ratio():
return (1 + math.sqrt(5)) / 2
gr = calc_golden_ratio()
inverse_gr = 1 - gr
numerator = math.pow(gr, n) - math.pow(inverse_gr, n)
return numerator // math.sqrt(5)
if __name__ == '__main__':
for n in range(0, 10):
n = str(n)
time = Timer("fib_closed_form(" + n + ")", "from __main__ import fib_closed_form")
print('Fib_Closed_Form(' + n +') = ' + str(time.timeit()))
time = Timer("fib_recursive(" + n + ")", "from __main__ import fib_recursive")
print('Fib_Recursive(' + n +') = ' + str(time.timeit()))
以下是值为1-10的函数的时序(时间以秒为单位,使用timeit模块测量)。默认情况下,每个调用由timeit模块进行1000000次,因此它是所有调用总计所需的时间的结果:
Python 3.2.2 (default, Nov 21 2011, 16:50:59)
[GCC 4.6.2] on staggerlee, Standard
>>>
Fib_Closed_Form(1) = 5.808775901794434
Fib_Recursive(1) = 0.6938691139221191
Fib_Closed_Form(2) = 6.142783880233765
Fib_Recursive(2) = 1.9276459217071533
Fib_Closed_Form(3) = 6.62189793586731
Fib_Recursive(3) = 3.6403379440307617
Fib_Closed_Form(4) = 6.376585960388184
Fib_Recursive(4) = 6.733421802520752
Fib_Closed_Form(5) = 6.566863059997559
Fib_Recursive(5) = 11.409136056900024
Fib_Closed_Form(6) = 6.521269083023071
Fib_Recursive(6) = 18.514809131622314
...
Fib_Closed_Form(10) = 6.631903886795044
Fib_Recursive(10) = 131.51839208602905
正如您所看到的,封闭形式具有更高的前期成本。递归的一个把它吹出水面!它只能通过n = 4的值保持竞争力。你可以看到它的时间越来越差。当我们达到n = 6左右时,我们已经看到这不是正确的方向。
顺便说一下,我昨晚尝试了n = 25。封闭的表格花了大约相同的时间,递归表格在我上床睡觉前没有完成(至少运行半小时)。
我的观点是,这些实现起来相当容易,并且可以直接进行一些单元测试。您可以尝试一下并在Java中查看自己的结果,尽管使用Java等语言的时序可能很复杂而无需额外的设置。