递归函数1

简单来说,递归函数就是自己调用自己,递归要包含递归的所有基本情况(有时我们叫做递归出口和递归调用)我们从一个简单的例子开始:打印一个数字所有位之和,例如 123 = 1 + 2 + 3, 9684 = 9 + 6 + 8 + 4

def sum_digits(n):
    if n < 10:
        return n
    else:
        all_but_last, last = n // 10, n % 10
        return sum_digits(all_but_last) + last

sum_digits(738)

问题被拆解为两个部分,加上前面的数和加上最后一位数,拆解后问题变得简单并且可以一直迭代继续拆解,具体的调用过程可以看一下我画的的environment diagram。

递归的剖析

递归函数的设计是为了简化原来的问题,而且有时候可以用其他设计方式解决。

例如计算一个数的阶乘

循环解决
def fact_iter(n):
        total, k = 1, 1
        while k <= n:
            total, k = total * k, k + 1
        return total
递归解决
def fact(n):
	if n == 1:
	    return 1
	else:
	    return n * fact(n-1)
	
	

那么递归函数的优势在哪里?

  1. 更加注重宏观上的设计,上面不考虑fact(n-1)是如何实现的
  2. 减少过程中变量的使用
  3. 注重问题的拆解,由繁到简

递归的互相嵌套

例如判断一个数是否为偶数,我们很容易得到一下思路

  1. 0为偶数
  2. 一个数为奇数如果这个数减一为偶数
  3. 一个数为偶数如果一个数减一为奇数

代码如下:

def is_even(n):
    if n == 0:
       return True
    else:
       return is_odd(n-1)
def is_odd(n):
    if n == 0:
        return False
    else:
        return is_even(n-1)

 还可以表示为:

  1. 一个大于二的数与它减二的数奇偶性相同
def is_even(n):
    if n == 0:
        return True
    elif n == 1:
        return False
    else:
        return is_even(n - 2)
  

 另外一个例子是一个二人游戏,一开始有n个石头,甲和乙轮流那石头,谁拿到最后一个石头就赢,规则如下:

  1. 甲每次拿一个
  2. 乙如果石头是偶数就那两个,奇数拿一个
  3. 甲先拿

设计一个函数,输入石头个数, 打印谁赢了

def play_jia(n):
    if n == 0:
        print("yi wins!")
    else:
        play_yi(n-1)
def play_yi(n):
    if n == 0:
        print("jia wins!")
    elif is_even(n):
        play_jia(n-2)
    else:
        play_jia(n-1)

 递归序

递归对于新手来说最烦的就是它的调用过程,递归序我这里不展开,那么如何可视化函数的调用过程,我们可以通过打印处理看一下,例如从大到小然后从小到大打印数字的前缀

>>> def cascade(n):
        if n < 10:
            print(n)
        else:
            print(n)
            cascade(n//10)
            print(n)

>>> cascade(2013)
2013
201
20
2
20
201
2013

实战

给出一个整数n,上限m,n可以由 1 到 m的数相加组成,返回有多少情况

例如  n = 6, m = 4 

  1. 6 = 2 + 4
  2. 6 = 1 + 1 + 4
  3. 6 = 3 + 3
  4. 6 = 1 + 2 + 3
  5. 6 = 1 + 1 + 1 + 3
  6. 6 = 2 + 2 + 2
  7. 6 = 1 + 1 + 2 + 2
  8. 6 = 1 + 1 + 1 + 1 + 2
  9. 6 = 1 + 1 + 1 + 1 + 1 + 1

一共有九种情况,返回9 

我们首先分析一下情况,列出所以基本情况:

考虑四个情况

  1.  n < 0  如果n搞着搞着发现小于0,那么这种情况不成立
  2.  m == 0   搞着搞着发现上限为0,那么情况不成立
  3. n == 0      n 刚好减到0,一种情况
  4. 返回 f(n-m, m) + f(n, m-1) 重点分析第四种情况:所有都可分为两种情况,一种至少含有一个上限m,一种不含上限m,

 

def count_partitions(n, m):
    if n == 0:
          return 1
    elif n < 0:
          return 0
    elif m == 0:
          return 0
    else:
          return count_partitions(n - m, m) + count_partitions(n, m-1)

思考下句话是否正确:

任何递归函数都可以改为非递归函数 

正确!我们可以手动实现函数压栈等过程

本文来自作者学习compsing programs的部分学习笔记

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值