神奇的兔子数列——算法学习笔记

发布于:2022-10-23 ⋅ 阅读:(436) ⋅ 点赞:(0)

等风来,不如追风去……

这是我参加“14天阅读挑战赛”第一周第二篇

点击查看“14天阅读挑战赛”详情,《趣学算法第二版》1.4 神奇的兔子数列



跟着小玉老师学算法
神奇的“兔子数列”
(递归、循环,哪个更好?)


  假设第1个月有1对初生的兔子,第2个月进入成熟期,第3个月开始生育兔子,而1对成熟的兔子每月会生1对兔子,兔子永不死去……那么,由1对初生的兔子开始,12个月后会有多少对兔子呢?
  兔子数列即斐波那契数列,它的发明者是意大利数学家莱奥纳尔多·斐波那契(Leonardo Fibonacci,1170—1250)。1202年,莱奥纳尔多撰写了《算盘全书》(Liber Abaci),该书是一部较全面的初等数学著作。书中系统地介绍了印度—阿拉伯数码及其演算法则,以及中国的“盈不足术”;此外还引入了负数,并研究了一些简单的一次同余式组。

  根据分析第一、二个月没有兔子新增数量都是1;第三个月成熟期的兔子会生一只兔子,总数2;第四月成熟期的兔子会生兔子,上月生的兔子成熟,总数3;第五月两只成熟的兔子生小兔子,上月生的成熟,总数5;第五月三只成熟的兔子生小兔子,上月生的成熟,总数8;……兔子这样一直繁衍下去……
  由兔子繁殖规律可见,每月新生兔子数都是上上个月的总数。

神奇的兔子数列公式图

在这里插入图片描述
  根据从兔子繁殖分析出的事件特性,可以用递归算法编写代码实现任意项的数列项推演。

递归代码

def resursive_rabbit(n):
    ''' 递归兔子数列 '''
    if n == 1 or n == 2:
        return 1
    else:
        return resursive_rabbit(n-1) + resursive_rabbit(n-2)

运行效果截图
在这里插入图片描述
在这里插入图片描述
  这?效率有点儿低啊😱能不能优化下哩?这主要是在递推和回归在计算和存储上费时费力。那就用列表和循环来试试。😄

代码

def for_rabbit(n):
    ''' for循环优化兔子数列 '''
    fib = [1]*n
    
    for i in range(2, n):
        fib[i] = fib[i-1] + fib[i-2]

    return fib[-1]

运行效果截图
在这里插入图片描述
  这!🧐这么快?👀
只是用一个列表来存储前面的项而已哦。等等,来算个10000项。😎
在这里插入图片描述
  耗时居然远远小于0.1秒。先不定义整个数列长度的列表,就第一、二项,后面的计算出来append到列表中,会不会更快?

代码

def for_rabbit_append(n):
    ''' for+append循环优化兔子数列 '''
    fib = [1, 1]
    
    for i in range(2, n):
        fib.append(fib[i-1] + fib[i-2])

    return fib[-1]

效果截屏图片
在这里插入图片描述

  和直接先定义n个元素长度的列表,几无差异(还是计算第10000项)。还可以优化不?只计算第几项,用列表存储整个数列,是不是有点儿浪费?用两个变量暂存上一项、上上项何如?

代码

def for_rabbit_ab(n):
    ''' for + a,b循环优化兔子数列 '''
    a, b = 1, 1

    for i in range(2, n):
        fib_new = b + a
        b, a = fib_new, b

    return b

代码运行效果截屏图片
在这里插入图片描述
  还是讲得第10000项,时间又少了一半!🤗

这神奇的兔子数列,还没通项公式哩,用她来试试:
在这里插入图片描述

代码

def formula_rabbit(n):
    ''' 通项公式兔子数列 '''
    from math import sqrt
    a, b = ((1+sqrt(5))/2)**n, ((1-sqrt(5))/2)**n
    return 1/sqrt(5) * ( a - b )

运行效果截图
在这里插入图片描述
计算第10000项数字表示溢出报错截屏图片
在这里插入图片描述
  由试炼可见,通项公式不但有浮点数计算误差,还可以算太多的项。速度也比不上列表+循环。所以最好不好用通项公式来整。😜

试试用三个优化的循环都计算一遍第10000项:
在这里插入图片描述
耗时还是远远小于0.1秒。😎😎😎


  一般来讲,同一需求都可以设计几种算法。当重复太多,递归费时费力,就要找出一个更优算法。我从优化算法的过程中,真切地体会到算法之美!


本文含有隐藏内容,请 开通VIP 后查看

网站公告


今日签到

点亮在社区的每一天
去签到