从递归开始讲起
首先我们要明白什么是递归?
递归算法在计算机科学中是指一种通过【重复将问题分解为同类的子问题而解决问题】的方法。 简而言之,就是将一个规模大的问题,不断分解为同类型的规模小的子问题。规模一旦小了,也就容易求解了。在进行分解的时候,分解到哪里/什么时候可以停止呢?到规模小到可以直接(或极其容易)得解的情况,就可以了。
递归求解问题的思路在于,在大问题分解到了为最小规模问题时,可以求得最小规模问题的解,这个时候再返回去,层层返回,最终就可以求得大问题的解了。
那么问题来了,如何将规模大的问题分解为规模小的问题呢?
在编程当中,递归算法是这样实现的:通过不断调用自身方法,只需改变其中的参数,使参数按一定规则往小的方向变化,就能做到将问题规模缩小化。 这也正是递归的核心所在。
递归的套路
递归算法发展至今可以说已经趋于规范化了,可以提炼和总结出它的结构组成。纵使递归的题目类型很多,具体内容也各有不同,我们只要掌握了递归算法的内在核心,再认识递归的模板套路,就能比较轻松地求解问题。
-
细读题目,抓住需求,了解要实现的具体功能
就像拿到一道数学题一样,我们首先需要品读题目,弄清楚这一题目要我们干嘛,让我们求些什么。然后对这一题目进行思考,可以用怎么样的数学方法进行解答,这个解决的方法,就是要实现的具体功能。 -
递归,规模缩小,写出达到最小规模问题的条件
我们递归的思路是不断将问题规模缩小化,但是最终,必须要有一个终止的条件,(无穷无尽的缩小没有意义),这个终止的条件,就是到达最小规模问题的条件。 -
“推卸责任”,调用自身方法,改变参数使规模变小,剩下的交给他们
我们要不断缩小参数的范围,在保证问题类型不改变的情况下,只让规模变小。我们只需完成一点点事情(看具体题目而定),然后将剩下规模的子问题,交给调用了的改变了参数范围的自身方法即可。 因为有第二点的终止条件限制,因此在到达最小规模子问题时,调用就会停下来。
递归模板参照
这是最简单、最一般性的递归模板:
public void RecursionMethod(参数) {
if (终止条件) {
return;
}
RecursionMethod(规模小的参数);
}
但是在实际编程题目中,很多递归在调用之前或者调用之后,都会有一些逻辑上的处理(这种处理因具体题目而异)。
因此可以将模板再细致化:
public void RecursionMethod(参数) {
if (终止条件) {
return;
}
逻辑运算...
RecursionMethod(规模小的参数i);
逻辑运算...
RecursionMethod(规模小的参数j);
……
}
写在后面
模板的使用其实是在自身掌握了这个知识点后才起到给人简易、便利的效果,是一个锦上添花的作用。
最重要的依然在于对算法的理解和思考。对于递归的介绍,希望读者能够耐心看看文章的文字叙述部分,加深对于递归的理解。 小编囿于水平,这里谈的也只是递归的简单分析,望读者们批评指正。后续会举出具体的例子来对递归做进一步的剖析,汉诺塔的例子会在后文着重介绍。