300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 三种方法求解Fibonacci(斐波那契)数列

三种方法求解Fibonacci(斐波那契)数列

时间:2022-07-15 04:46:12

相关推荐

三种方法求解Fibonacci(斐波那契)数列

三种方法求解Fibonacci(斐波那契)数列

(一)

所谓Fibonacci数列是指这样一种数列,它的前两项均为1,从第三项开始各项均为前两项之和。用数学公式表示出来就是:

1 (n=1,2)

fib(n)=

fib(n-1)+fib(n-2) (n>2)

可以证明斐波那契数列的通项公式为fib(n) = [(1+√5)/2]^n /√5 - [(1-√5)/2]^n /√5 (n=1,2,3.....),关于斐波那契数列的详细介绍请参阅百度百科。

下面我将介绍三种比较常用的求解第n项斐波那契数列的方法:递归法、迭代法、通项公式法。

1、递归法

这种方法的优点是简洁和容易理解,缺点是时间复杂度太大,随着n的增大,运算时间将会急剧增加。因此在很多场合这种方法是不可取的。

使用这种方法的关键代码是:

if(n == 1|| n== 2)

{

return 1;

}

else

{

return fib(n - 1) + fib(n - 2);

}

2、表驱动的递归法

这里不提纯粹的表驱动法,因为对于项数未知的Fibonacci数列开启大片的空间来换取时间未免不值得且不负责。我们只是为了消除递归法中大量重复的运算,可以将已经计算过的中间值存入一个表,已备后续使用:

#define MAX_LOG 20

static unsigned long Logs[MAX_LOG] = {0};

unsigned long Fib(int n)

{

if (n <= 1) {

return n;

} else if (n < MAX_LOG && Logs[n] != 0) {

return Logs[n];

} else {

Logs[n] = Fib(n - 1) + Fib(n - 2);

return Logs[n];

}

}

(二)

当n小于保存的表长时,由于每个中间值只计算一次,时间复杂度降为O(n)。但随着n的增大,要想维持O(n)的时间复杂度,就必须扩大保存的表长,这就造成了存储空间的浪费。

3、迭代法

这种方法相对于递归法来说在时间复杂度上减小了不少,但代码相对就要复杂些了。它的思想是这样的,假设开始时f0=1,f1=1,currentFib表示当前斐波那契数,则:

for(i = 1;i < n;i++)

{

currentFib = f0 + f1;

f0 = f1;

f1 = currentFib;

}

这样迭代结束和currentFib就是fib(n)了。

4、转移矩阵法。此方法通常见于线性代数中的Markov过程示例。Fibonacci数列第n项与第n-1项可以通过转移矩阵的n-1次迭代求出:

function y = Fib(n)

first = [1; 0];

trans = [1 1; 1 0];

last = trans ^ (n - 1) * first;

y = last(1, 1);

end

此算法的时间复杂度相当于计算矩阵乘方的时间复杂度。在计算2阶矩阵n次方时,如果直接按矩阵乘法定义式展开,不加特别优化,其时间复杂度为O(n)。

5、通项公式法

这种方法是最没技术含量的方法,只要你知道通项公式照着把它翻译成编程语言就可以了,优点不言而喻。function y = Fib(n)

sr5 = sqrt(5);

y = uint32((((1 + sr5) / 2) ^ n - ((1 - sr5) / 2) ^ n) / sr5);

end

该方法的时间复杂度貌似为O(1),但我们还应该考虑乘方运算的时间消耗。不加特别优化时,用乘法实现n次乘方的时间复杂度为O(n)。考虑到浮点数计算效率和精度问题,此方法在计算机实现时不如转移矩阵法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。