Python经典算法(小白入门系列)------递归的应用场景(含斐波那契数列)

0.递归的概念

概念:递归算法是一种直接或者间接的调用自身算法的过程

以下内容的总结非常重要,刚开始看的时候不以为然,但经过很多案例的总结之后,发现核心的还是这些内容。领悟核心内容,才方便后续举一反三!

特点:
①递归就是在过程或者函数里调用自身。
②在使用递归策略时,必须有一个明确的递归条件,称为递归出口。
③递归算法解题通常显得很简洁,但递归算法解题的效率较低。所以一般不倡导使用递归算法设计程序。
④在递归调用的过程当中系统的每一层的返回点、局部变量等开辟了栈来存储。递归函数次数过多容易造成栈溢出等。所以一般不倡导用递归算法设计程序。

四个条件:
每次在调用规模上都有所缩小(通常是减半),即从大到小开始计算和或积等
相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)
③ 在条件的规模最小值的时候,需要给出直接的结果。因此,每次递归调用都是有条件的(以条件的值未达到最小的值为递归条件)
④无条件的递归调用将会成为死循环而不能正常结束

递归算法一般用于解决三类问题:
(1)数据的定义是按递归定义的。(比如斐波那契数列)
(2)问题解法按递归算法实现。(回溯)
(3)数据的结构形式是按递归定义的。(比如树的遍历,图的搜索,二分法查找等)

1.普通递归

案例一:求1 + 2+ 3+…+n 的和


def cal_sum(n):			# n代表从1共计加到n
	res = None
	if n == 1:			# 在递归之前,先确定最小值情况的结果
		res = 1
	elif n > 1:			# 从最大值开始,递减的时候,结果情况
		res = n + cal_sum(n-1)
	return res

案例二:求3 + 6+ 9+ 12+…+n 的和

求n个如上规律数组的和

  • 如上发现,其实是案例二是案例一的一个简单升级,最终要求N个数的和
  • 3代表第一个数,6代表第二个数。如果把第N个数看做索引,那每个索引对应的数值就是索引乘以3

def cal_sum(n):
    res = None
    if n == 1:
        res = 3							# n为第一个索引的时候,先确定res的值
    elif n > 1:
        res = 3*n + cal_sum(n - 1)		# 原理同上
    return res

  • 以上两个案例,每个索引的数值,都只和索引有关系,与前一个数的大小似乎没关系。
  • 在第一节部分,总结的四个条件中,第二个条件(前一次要为后一次做准备)没有在如上两个案例中体现,但往往这个部分,才是我们最棘手的问题。


2.斐波那契数列—递归求值

例如,0、1、1、2、3、5、8、13、21、34…这样的数列,第三个数值,是前面两个数值之和,求第N个数的值?

  • 以上部分,就会用到我们上面谈到的,前一次或前二次的数据,要为下一个数值做好准备,这样才能层层递进
  • 而一般递归都是条件的值,从大到小排序的,所以如果计算第n个数值的大小,使用feibo(n),那么就需要计算feibo(n-1) + feibo(n-2)的和。而计算feibo(n-2)的值,就需要计算feibo(n-3)+fiebo(n-4)的和
  • 依次往复,知道我们能知道的feibo(1) 和feibo(2)的值

def feibo(n):
    n1 = 0
    n2 = 1
    last = None
    if n == 1:
        last = n1
    elif n == 2:
        last = n1 + n2
    elif n >= 3:
        last = feibo(n-1) + feibo(n-2)		# 此处容易产生很大的开销,特别是递归深度很深的时候
    return last

  • 递归相对运行效率低,每一次调用函数都要开辟栈帧。
  • 递归调用的深度不宜过深,python对递归深度做了限制,以保护解释器,超过递归深度限制,抛出RecursionError。sys.getrecursionlimit()


3.斐波那契数列—循环求值

循环方式求值:


def feibo_num(n):
    my_list = list()
    n1 = 0
    n2 = 1
    if n == 1:
        my_list.append(n1)
    elif n == 2:
        my_list.append(n1)
        my_list.append(n2)
    elif n > 2:
        i = 2							# 因为n1, n2已经确定了,需要从第三个数开始求值,所以设置i=2 
        my_list.append(n1)
        my_list.append(n2)
        while (i < n):
            last = n1 + n2
            n1, n2 = n2, last			# 要求得last的值,n1, n2需要层层递进,然后才有last的值
            my_list.append(last)
            i += 1
    return my_list

循环方式求值,这种方式内存开销要小很多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hello-alien

您的鼓励,是我最大的支持!

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

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

打赏作者

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

抵扣说明:

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

余额充值