斐波那契数列的三种解法

斐波那契数列是面试过程中很基础的问题,数列的定义如下所示,每个数字都可以拆解成之前两个数的和,直至拆解到0和1的组合。这种递归拆解的问题,如果拆解算法取用的方式不同,计算量和计算速度有着天壤之别。

1.采用树形递归进行求解

采用树形递归方法,作为典型的树形递归具有教育意义,但是却是一种很糟糕的计算方式,因为做了太多的冗余计算。

 

可以证明Fib(n)值的增长相对于n是指数关系,该过程所用的计算步骤数将随着输入增长而指数性的增长,另一方面其空间需求随着输入增长而线性增长,因为, 在计算中的每一点,我们都只需保存树中在此之上的结点的轨迹。一般说,树形递归计算过程里所需的步骤数将正比于树中的结点数,其空间需 求正比于树的最大深度。

 

2.Fib(n)就是最接近某个表达式的整数

该表达式如下所示:

 

其中∅就是黄金分割比,满足如下表达式

 

 

这是一个经验总结,至于如何推导也没搞明白,但确是正确的

3.以线性迭代的方式计算斐波那契数列

(define (fib n)
    (fib-itor 1 0 n))
(define (fib-iter a b count)
    (if (= count 0)
        b
        (fib-iter (+ a b) a (- count 1))))    

计算Fib(n)这种方法是一个线性迭代,和树状展开相比这两种方法在计算所需的步骤上有很大的差异巨大,后一个方法相对于n为线性的,前一个相对于n是指数的。虽然第一个fib过程远比第二个低效,但它却更加直截了当,基本上就是将斐波那契序列的定义直接翻译为Lisp语言。

下面通过C++语言实现三种计算斐波那契数列的方法,供大家参考,大家可以比较一下计算效率。

#include <iostream>
long long fib(int n)
{
	if (n == 0)
	{
		return 0;
	}
	if (n == 1)
	{
		return 1;
	}
	return fib(n - 1) + fib(n-2);
}
long long fib_split(int n)
{
	double splitValue = (1.0 + sqrt(5)) / 2.0;
	return round(pow(splitValue,n) / (double)sqrt(5));
}

long long fib_thread_sub(int a, int b, int count)
{
	if (count == 0)
	{
		return b;
	}
	return fib_thread_sub(a + b, a, count - 1);
}

long long fib_thread(int n)
{
	return fib_thread_sub(1, 0, n);
}
int main()
{
	for (int index = 0; index < 20; ++index)
	{
		std::cout << fib(index) << ":" << fib_split(index) << ":" << fib_thread(index) << std::endl;
	}

}

没有对比就没有伤害,当n的值足够大的时候,三种解法的计算速度有着天壤之别,所以说在解决特定的问题的时候换个思路可能会有意想不到的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农飞飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值