python定义函数计算斐波那契公式前20的项_Python3算法之二:斐波那契函数

关注微信公众号“酸痛鱼”,获得更多最新最全的文章。

本文中所涉及的代码,在未特殊声明的情况下,都是基于Python3程序设计语言编写的。

建议您在PC浏览器中阅读本文,以获得更好的阅读体验。

如果您未掌握知识提要中的内容,建议您先掌握这些内容之后再阅读本文。

知识提要

1、斐波那契函数

2、函数的定义、递归

3、时间复杂度、空间复杂度

4、作用域、关键字global

0

什么是斐波那契函数

斐波那契数列,是指这样一个数列:

1、1、2、3、5、8、13、21、24、55……

其特点是,n>=3时,第n项的值为第n-2项和第n-1项的和。我们用f(n)表式其递推公式,即第n项的值,则:

f(n) = f(n-2) + f(n-1) ; n>=3, f(1)=1, f(2)=1

我们将这个递推公式称为斐波那契函数。

1

递归方式实现斐波那契函数

斐波那契函数的定义是递归定义,我们很容易想到递归的方式。话不多说,我们直接看代码。

def fib(n):

# 递归结束条件

# 为了处理方便,n <= 0 时,直接返回 1

if n <= 2:

return 1

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

没错,四行代码,我们就实现了一个算法题目。但这个代码的效率是非常低的。

使用递归的方式,会出现很多重复的运算。例如,当我们计算fib(5)的时候,会递归调用fib(4)和fib(3),其中fib(4)又会重复计fib(3)。

事实上,这种实现方式的时间复杂度O(2^n),空间复杂度为O(n)。

巧合的是,对于一次fib(n)调用,假设其实返回值为An,函数fib被递归调用的次数为2 * An - 1。我们可以写个代码验证一下。至于为什么有这个巧合,感兴趣的读者可以运用数学的方式推算一下。

calls = 0 # 全局变量,用于记录fib被调用的次数

def fib(n):

global calls # 声明使用全局的calls,而非重新创建局部的变量

calls += 1

if n <= 2: return 1

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

def test(n):

global calls

calls = 0

an = fib(n)

print("n:{}, fib(n):{}, calls:{}".format(n, an, calls))

if __name__ == "__main__":

test(1)

test(2)

test(3)

test(10)

test(20)

test(30)

以上代码的运行结果如下:

n:1, fib(n):1, calls:1

n:2, fib(n):1, calls:1

n:3, fib(n):2, calls:3

n:10, fib(n):55, calls:109

n:20, fib(n):6765, calls:13529

n:30, fib(n):832040, calls:1664079

2

线性方式实现斐波那契函数

斐波那契数列的特点是,第N项的值为第N-1项和第N-2项的和。同理,N+1项的值为第N项和N-1项的和。

所以,在程序实在的层面上,我们可以通过不停的记录N和第N-1,来求得新最新的第N项的和。通过这种方式,我们可以时间复杂O(n)的方式实现斐波那契函数,同时,其实空间复杂度也仅为O(1)。

def fib(n):

an_1 = 1 # 第n-1项

an = 1 # 第n项 (初始为第2项)

# 至少从第3轮才循环迭代

i = 3

while i <= n:

i += 1

# 左边为最新值,右边为上一轮的值

an_1, an = an, an + an_1

return an

3

通项公式

斐波那契数列的通项公式为:

理论上,根据通项公式实现斐波那契函数,时间复杂度为O(1)。但事实上,如果我们按照这个公式去写代码,并不能得到正确的解。这是因为计算在处理浮点数的时候,并不总能保证其实精度。

计算机领域,有一个学科叫《科学计算》,就涉及到浮点数精密计算的问题,感兴趣的读者可以去了解一下。微信扫码关注我嗄嘎嘎

酸痛鱼,与你分享快乐的代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值