python之递归

1.什么是递归

所谓递归就是在函数定义中调用函数自身的方法,而递归的思想就是将规模大的问题转化为规模小的,具有与原来问题相同解法的问题来解决。

def func():
    print('jj是很帅的')
    func()
func()
# >>> maximum recursion depth exceeded while calling a Python object
# >>> 调用 Python 对象时超出最大递归深度

那么问题来了,什么是最大递归深度?

递归深度:通俗来讲就是自己调用自己的最大次数,在python中递归深度为1000,也就是说自己调用自己最多1000次,而其实,当调用次数小于1000时就已经抛出异常

count = 1
def func():
    global count
    print('这是第%s'%count)
    count = count + 1
    func()
func()

# >>> 这是第996  最大到996次

2.递归的特点

1、必须有一个明确的结束条件
2、每次进入更深一层递归时,问题规模(计算量)相比上次递归都应有所减少

3.递归的使用方法

找到递归关系,即把一个复杂的问题转化为与它形式相似、但规模较小的问题。

找到递归出口,即问题转化时,当规模足够小,可以直接求解

举个栗子:

遍历D:/Program Files文件夹,打印出所有的文件和普通文件的文件名
import os

def func(filepath,n):
    files = os.listdir(filepath)
    # 获取到文件的路径

    for file in files:
        file_p = os.path.join(filepath, file)

        if os.path.isdir(file_p):
            print('\t*n',file)
            func(file_p,n+1)
        else:
            print('\t*n',file)

func("D:/Program Files",1)

4.递归的应用

(1)斐波那契数列

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(≥ 2,∈ N*)在现代物理、准晶体结构、化学等领域,斐波那契数列都有直接的应用

代码如下:

def fab(n):
    if n <= 2:
        return 1
    else:
        return fab(n-1)+fab(n-2)
 
 
n = eval(input())
print(fab(n))

2.赶鸭子问题

题目描述
一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?

分析
设经过的村子为n (n = 0,1,2,...,7),根据题目分析可知递归结束的出口: n = 7时,剩余鸭子数duck = 2;

分析递归体:从后向前推 n=7时 ,duck = 2, 由于每经过一个村子,卖去所赶鸭子的一半又一只,因此七个村子后剩余的鸭子数 duck[7]=duck[6]-(duck[6]/2+1)

反推duck[6] = (duck[7] + 1) * 2

最终递归体: (duck[n+1] + 1) * 2;
代码如下:

def duck(n):
    if n == 7:
        return 2
    else:
        return (duck(n+1)+1)*2
 
 
print("鸭子的总数为:{}".format(duck(0)))
sum = duck(0)
for i in range(1, 8):
    print("第{}个村庄卖出{}只鸭子,剩余鸭子数为{}". format(i, sum-duck(i), duck(i)))
    sum = duck(i)

3.二分查找

在一个有序数列中,通过二分法查找出某一个数。二分法查找一次性能排除一半的元素,效率非常快,但最大的弊端在于只能针对有序数列

递归版本二分法
ls = [1,2,5,9,11,22,33,44,55,66,77,89,99,111,222]
def func(n,left,right):
    print('哈哈哈')
    if left < right:
        mid = (left+right) // 2
        if n > ls[mid]:
            left = mid + 1
            func(n,left,right) # 递归的入口
        elif n < ls[mid]:
            right = mid - 1
            func(n,left,right)
        elif n == ls[mid]:
            print('找到了')
            return mid # 通过return返回,结束递归
    else:
        print('没有这个数')
        return -1 # 如果找不到返回-1,没有这个数。索引的起始值一般为0.


# 找n,左边界:0 右边界 len(ls) -1
ret = func(88,0,len(ls)-1)
print(ret) 

# >>> None

这段代码中明确写出,如果找不到该数字,最终返回的是-1,而实际运行下来返回的是None,为什么呢?

递归是一层一层向下执行,如果最终问题解决,会返回值,而它只会返回到调用它的那一层,因此在递归时,要在每一层都加入return,才能将值返回到最外层

修改之后的代码如下:

ls = [1,2,5,9,11,22,33,44,55,66,77,89,99,111,222]
def func(n,left,right):
    print('哈哈哈')
    if left < right:
        mid = (left+right) // 2
        if n > ls[mid]:
            left = mid + 1
            return func(n,left,right) # 递归的入口
        elif n < ls[mid]:
            right = mid - 1
            return func(n,left,right)
        elif n == ls[mid]:
            print('找到了')
            return mid # 通过return返回,结束递归
    else:
        print('没有这个数')
        return -1 # 如果找不到返回-1,没有这个数。索引的起始值一般为0.


# 找n,左边界:0 右边界 len(ls) -1
ret = func(88,0,len(ls)-1)
print(ret)  # 在每一层返回,最终找不到返回-1

# >>> -1

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值