Python函数递归

一、递归函数简介

1、递归概述

  • 递归是解决问题的一种方法,它将问题不断分成更小的子问题,知道子问题可以用普通方法解决。同常情况下,递归会使用一个不停调用自己的函数,尽管表面上看起来很普通,但是递归可以帮助我们写出非常优雅的解决方案。对于某些问题,如果不用递归就很难解决。

2、递归特性

①递归本身是一个函数,需要函数定义方式描述
②函数内部,采用分支语句对输入参数进行判断

3、循环自身调用

def demo():
    print('Python 真好玩')
    demo()
demo()
  • 上述代码中,创建了自定义函数demo(),函数内部不断调用自身,代码的执行结构为重复输出字符串’Python 真好玩’,输出次数不超过1000次,这是因为一个函数最多只能调用低级1000次,重复调用会导致栈内存溢出那么demo()函数是递归函数吗?

4、递归函数三原则

  • 正如科幻作家阿西莫夫提出的机器人三原则一样,一个自定义函数想成为递归函数必须要遵循以下三个原则:
    ①递归算法必须具有基本情况
    ②递归算法必须改变其状态像基本情况靠近
    ③递归算法必须以递归的方式调用自己

  • 按照上述三种原则可以去对比一个函数是否为递归函数,像前面所述demo()函数并没有基本情况,只是进行了调用自己,因此不属于递归函数。

二、递归求阶乘

  • 在根据题意编写递归程序时,需要提前获取以下两个内容:
    ①此题的基本条件(基例)
    ②问题分解过程层级关系(链条)

  • 输入整数n,输出n的阶乘:假设目前需要求整数5的阶乘,5阶乘的结果并不能一眼得知,但是层级关系为5!=5 * 4!,4!=4 * 3!..,这样就可以将5!一步步向下分解,知道分解至1!=1 * 0!,基例为0!是一个已知值1。即针对一个正整数n,当n为0时,阶乘结果为1,当n不为0时,阶乘结果为n * (n-1)!,因此可以得出一下公式:
    在这里插入图片描述

  • 根据所获取的基例及链条所写出公式可以进行编写代码。

    def fact(n):
        if n==0:#如果n的值为基例情况
            return  1#返回基例情况的结果值
        else:
            return n*fact(n-1)#链条关系当前n乘以(n-1)的阶乘
    print(fact(5))
    
    #120
    
  • 在上述代码运行过程中,我们需求计算整数5的阶乘。
    先将5作为fact()函数的参数会先计算 5 * 4!;
    再将4作为fact()函数的参数再次传入计算4 * 3!;
    再将3作为fact()函数的参数再次传入计算3 * 2!;
    再将2作为fact()函数的参数再次传入计算2 * 1!;
    再将1作为fact()函数的参数再次传入计算1 * 0!;
    再将0作为fact()函数的参数再次传入计算。
    这时会发现if判断成立,
    将返回值1作为fact(0)的结果返回给0!,那么 1!=1 * 0!=1 * 1=1;
    将返回值1作为fact(1)的结果返回给1!,那么 2!=2 * 1!=2 * 1=2;
    将返回值2作为fact(2)的结果返回给2!,那么 3!=3 * 2!=3 * 2=6;
    将返回值6作为fact(3)的结果返回给3!,那么 4!=4 * 3!=4 * 6=24;
    将返回值24作为fact(4)的结果返回给4!,那么 5!=5 * 4!=5 * 24=120;
    最终再将返回值120返回给fact(5)便会得到最终结果为120.
    通过上述描述,我们会发现递归函数在运行过程中会经历两个过程:
    ①逐步分解向下调用的过程(递推)
    ②判断调和成立后逐步将返回值向上返回的过程(回溯)
    调用函数fact(5)代码递推和回溯过程如图所示,其中蓝色箭头表示递推过程,红色箭头表示回溯过程。
    在这里插入图片描述

三、斐波那契数列

1、斐波那契数列定义

  • 斐波那契数列概念:
    斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契,以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列,第一项为1,第二项为1,从第三项开始,每一项的数字为前两项之和:1、2、3、5、8、13、21、34…

  • 兔子数列:
    假设一只刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一只小兔,并且此后每个月都生一只小兔,假设兔子不会发生死亡,问:一只刚出生的兔子,n月内繁殖成多少只兔子?
    兔子每月具体数量如图所示:
    在这里插入图片描述

  • 显然在图中,我们实线框表示的是成熟兔子,虚线框表示的是小兔子。从右边这一列的数字我们发现是有规律的。第一个数和第二个数为1,之后的每一个数都为
    前两个数之和。
    那么,我们如何将上述问题用Python代码来实现呢?首先,会发现我们已知第一个月和第二个月兔子数量必然是1,这可以作为代码的基例,除前两个月外,第n月的兔子数量为第n-1个月和第n-2个月的兔子数量之和,即f(n)=f(n-1)+f(n-2),这可以作为代码的链条,因此可以得出以下公式:
    在这里插入图片描述

  • 根据所获取的基例及链条所写出的公式可以进行编写代码。

    def fibo(n):
        if n<=2:
            return 1
        else:
            return fibo(n-1)+fibo(n-2)
    print(fibo(7))
    
    #13
    

2、斐波那契数列实例变化

  • 某种病毒具有很强的繁殖能力,从病毒粒子出生后的第五分钟开始,每分钟可以复制出一个新的病毒粒子。新出生的病毒粒子从第5分钟开始,也可以复制一个新的病毒粒子。前10分钟时的病毒粒子总数为10.,总数分别为:1,1,1,1,2,3,4,5,7,10。

  • 根据题目可以分析得出前4分钟病毒粒子数量始终为1,这可作为代码的基例,除前4分钟之外第n分钟病毒粒子数为第n-1分钟和第n-4分钟病毒粒子数之和,即f(n)=f(n-1)+f(n-4),这可以作为代码链条,因此可以得出以下公式:
    -

  • 根据所获取的基例及链条所写出公式可以进行编写代码:

    def virus(n):
    	if n<=4:#如果n<=4为基例情况
    		return 1
    	return virus(n-1)+virus(n-4)#链条为参数为n-1和参数为n-4函数返回值之和
    print(virus(10))
    
    #10
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值