递归

递归是一种编程方法,指的是函数调用自身来实现某种功能。递归只是让函数更容易理解,并没有性能上的优势

基线条件和递归条件

由于递归是函数调用自身,所以编写使用递归的程序很容易出错。每个递归函数都应该包含两部分:基线条件和递归条件。基线条件指的是递归函数停止调用自身的条件,递归条件指的是函数调用自身的条件。基线条件一般是我们最容易处理的情况或者是我们的目标

阶乘函数

在使用递归编写阶乘函数时,我们应该首先确定的是该函数的输入输出:给定某个值,返回其阶乘。再确定基线条件:如果给定的值是1,则返回1。再确定递归条件:如果给定的值不是1,则应该调用自身。
代码如下:

def fact(x):
  if x == 1:
    return 1
  else:
    return x * fact(x-1)

祖母的手提箱

你发现祖母有个手提箱,且祖母告诉你钥匙在一个盒子里,盒子里面又有许多盒子,某个盒子中有一把钥匙。你要从这些盒子中找到这把钥匙。
装有钥匙的盒子
如何使用递归解决这个问题?首先明本基线条件应该是什么,即我们什么时候应该停止递归:如果找到了钥匙则应该停止。然后要明白递归条件是什么:如果找到的是盒子,则应该调用函数本身继续在盒子中查找钥匙。
伪代码如下:

def look_for_key(box):
  for item in box:
    if item.is_a_box():  # 递归条件 
      look_for_key(item)
    elif item.is_a_key():  # 基线条件
      print("found the key!")

分而治之

分而治之是一种递归式问题解决方法。即我们在递归时要尽量将问题的规模缩小。如上面的阶乘问题,我们将n的阶乘问题转换成n-1的阶乘问题,这样一来就会慢慢接近基线条件——求1的阶乘问题。

数组求和

如何使用分而治之的思想对一个数组求和?假如我们有一个数组arr=[2,4,6],对这个数组进行求和。
首先确定基线条件,即最简单的情况:如果一个数组为空,那它的和就是0(或者一个数组只有一个元素,那它的和就是这个元素)。
接下来思考如何减小原问题的规模,注意到:一个数组可以分为两个部分:首元素和其余元素。数组的和就等于这两部分的和,即sum([2,4,6]) = 2 + sum([4,6])。这样一来原先要对有三个元素的数组求和,现在只要对两个元素的数组求和,减小了问题的规模,同时这样一直递归下去也会达到基线条件,即可解决问题。

土地划分

你是一个农场主并有一块土地,土地长1680m,宽640米。
你的土地
你现在要将这块土地均分成许多小方块,并要保证分的小方块尽可能大。
这个问题可以通过找长和宽的最大公约数来解决。
接下来我们使用递归来解决这个问题:
首先确定基线条件,也就是我们最容易处理的情况。如果有一块土地,它的长是宽的整数倍,那我们可以很容易地将其均分为若干个方块,如下:
最容易处理的情况
接下来我们要想办法减小问题的规模,如下,首先在土地以较短边作正方形,将土地划分:
在这里插入图片描述
注意到:余下的部分所能支持的最大方块就是整个土地所支持的最大方块。因此我们只需要求出余下部分所支持的最大方块即可。这样一来我们将较大土地的划分问题转换成较小土地的划分问题,成功减小了问题的规模。再对较小的土地递归调用该算法即可求解。

更多例子

汉诺塔问题

def move(n, a, b, c):
    if n == 1:
        print('move a planet from', a, 'to', c)
    else:
        move(n-1, a, c, b)
        move(1, a, b, c)
        move(n-1, b, a, c)


move(3, 'A', 'B', 'C')
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值