递归算法详解

本文深入探讨了递归的概念,通过一个数的阶乘示例和汉诺塔问题的实战解析,阐述了递归解决问题的思路。递归算法的特点包括将问题分解为相同结构的子问题以及存在基础终止条件。在实践中,应判断问题是否符合这两个特点以决定是否适用递归。通过递归解汉诺塔问题,展示了如何定义递归函数并利用递推公式逐步解决问题。
摘要由CSDN通过智能技术生成

前言

最近在做机器学习的练习中,有很多经典算法中都穿插着递归的思想,可能有很多人跟我一样听过这样一句话:“能用递归解决的问题都可以用循环解决”。所以经常会忽略递归在算法中的运用,本文对使用递归的思想解决问题进行详细的解释,加强对递归思想的灵活运用。


一、什么是递归

简单来说:函数中存在着调用函数自身的情况

递归其实可以看做两部分操作,一步步去寻求子问题的解是“递”;得到最基本的子问题的解之后,再一步步返回求上一层的解是“归”

用一个非常简单的”查字典“的例子来解释这个思想:

  1. 你在学习过程中与到了一个很生疏的词语1,你不知道它是什么意思,于是你打开字典,在字典中找到了对它的解释,但是在解释它的这句话中,又存在另一个生疏的词语2,于是你又在字典中查找词语2的解释,结果词语2中也有一个生疏的词语3,在字典中继续查找,就这样不断重复这个过程,直到对词语的解释中没有生词,这时“递”这个过程就结束了;
  2. 但是我们不要忘记我们的初衷,是为了找词语1的意思(像极了解决报错的时候一个又一个,最后差点忘了最原始的报错是什么),然后我们需要从最后一个词语开始,向上解释,一步一步地解释到我们最开始想要知道的那个词语的解释中,这就是“归”的过程

一个简单示例,求一个数n的阶乘:

f(n) = n*(n-1)(n-2) … 21
也就是
f(n) = nf(n-1)

python代码

def func(n):
   if n == 1:
       return 1
   else:
       return n * func(n - 1)
print(func(3))

二、递归算法的使用思路

通过以上的解释,我们可以发现,递归有两个特点:

  1. 一个问题可以分解成具有相同解决思路的子问题,子子问题,这些问题都能调用同一个函数(相同解决思路
  2. 经过层层分解的子问题最后一定是有一个不能再分解的固定值的,如果没有的话,就无穷无尽地分解子问题了,问题显然是无解的。(终止条件

我们在解决问题时可以通过判断问题是否具有以上两个特点来确定是否可以用递归来解决
确定问题可以使用递归来解决的话,就来看看解决递归问题的大概思路:

1.先定义一个函数,明确这个函数的功能
2.寻找问题与子问题间的关系(递推公式),补充到第一步中

三、实战练习

汉诺塔问题

如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数
在这里插入图片描述
根据解体思路:
1.定义递归,明确函数的功能:A 上面的 n 个圆盘经由 B 移到 C

move(n,a,b,c)

2.寻找问题与子问题间的关系(递推公式)
首先来看一下如果A上只有两块圆盘怎么移
在这里插入图片描述
分析问题与子问题的关系,要将 n 个圆盘经由 B 移到 C 柱上去,可以按以下三步来分析:
将 上面的 n-1 个圆盘看成是一个圆盘,这样分析思路就与上面提到的只有两块圆盘的思路一致了
将上面的 n-1 个圆盘经由 C 移到 B

move(n - 1, a, c, b)

此时将 A 底下的那块最大的圆盘移到 C
再将 B 上的 n-1 个圆盘经由A移到 C上

move(n - 1, b, a, c)

注意:由于之前已经定义好了这个函数的功能,那么接下来的把 n-1 个圆盘 经由 C 移到 B 就可以很自然的调用这个函数,所以明确函数的功能非常重要,按着函数的功能来解释,递归问题其实很好解析,第一步的 n - 1 从 C 移到 B,重复上面的过程,只要把 上面的 n-2个盘子经由 A 移到 B, 再把A最下面的盘子移到 C,最后再把上面的 n - 2 的盘子经由A 移到 B 下…, 就找到规律了,不过在找问题的过程中 ,切忌把子问题层层展开,这样这就陷入了递归的陷阱,计算机都会栈溢出,何况人脑

代码

def move(n, a, b, c):
    if n == 1:
        print(a, '-->', c)
    else:
        move(n - 1, a, c, b) 
        print(a, '-->', c)
        move(n - 1, b, a, c)
move(3,"A","B","C")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

.别拖至春天.

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值