1、递归
1.1、什么是递归
递归指的是一种通过重复将原问题分解为同类的子问题而解决的方法。简单来说就是在运行的过程中,直到碰到终止条件,然后再返回结果的过程。
其基本思想就是:把规模大的问题不断分解为形式相同的子问题来解决。
由上述可以知道,可以把递归分为两个过程:[递推过程] 和 [回归过程] 。
递推过程:就是将本来的问题一层层的分解为与原问题形式相同,规模更小的子问题,直到达到结束条件时停止,然后返回底层的解。
回归过程:从最底层子问题的解开始,一层一层的回归,最后回到最开始递推的原问题,最后返回原问题的解。
1.2、递归的适用范围
由递归的基本思想可以得到,一个问题若是需要用递归需满足三大要求:
① 该问题是否可以分解为规模更小的子问题?
② 该问题的子问题的求解思路是否与原问题相同?
③ 若满足上述两点,则需考虑递归的终止条件是什么?(一个没有终止条件的递归,就是一个死循环。)
1.3、递归的解题思路
在写递归的时候,可以按照递归的基本思想来写,可以将递归的解题思路分为三步:
① 写出递推公式:找到将原问题分解为子问题的规律,并且根据规律写出递推公式。
② 明确终止条件:推敲出递归的终止条件,以及递归终止时的处理方法。
③ 将递推公式和终止条件翻译为代码:
Ⅰ.定义递归函数:明确函数意义、传入参数、返回结果等。
Ⅱ.书写递归主体:提取重复的逻辑,缩小问题规模。
Ⅲ.明确递归终止条件:给出递归的终止条件,以及递归终止时的处理方法。
1.4、递归算法的应用
来讲讲大家应该都听过的斐波那契数。
题目内容:
斐波那契数 (通常用 F(n)
表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1
给定 n
,请计算 F(n)
。
题目示例:
输入:n = 4 输出:3 解释:F(4) = F(3) + F(2) = 2 + 1 = 3
解题思路:
① 写出递推公式:观察原问题,可以发现其分解为子问题的规律,确定出递推公式。F(n) = F(n-1) + F(n-2)。
② 明确终止条件:题目内容给出的F(0) = 0,F(1) = 1。
③ 翻译为递归代码:
Ⅰ.定义递归函数:fibonacci(int n),传入的参数为int型的n,n代表问题的规模,返回的内容是第n个斐波那契数。
Ⅱ.书写递归主体:return fibonacci(n - 1) + fibonacci(n - 2).
Ⅲ.明确递归终止条件:明确终止条件 if (n == 0 || n == 1) { return 1; }
代码如下:
public static int fibonacci(int n){
if (n == 0 || n == 1) { //终止条件
return 1;
}
if (n > 2) {
return fibonacci(n - 1) + fibonacci(n - 2); //递归调用
}
return -1; //如果输入错误的n,一律返回-1
}
1.5、递归算法的题目
2、分治:
2.1、什么是分治
分治可以理解为分而治之,就是把一个复杂的问题分为两个或两个以上相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解为子问题解的合并。
其基本思想就是:把规模大的问题不断分解为子问题,使得问题规模减小到可以直接求解为止。(注意和递归的区别哦)
2.2、分治和递归的异同
由上可知,两个算法都是将规模大的问题不断分解为子问题。那么两者又有什么异同呢?递归其实和分治之间存在一种包含关系,即递归算法 ∈ 分治算法。
2.3、分治的适用范围
需要用分治算法解决的问题,需要满足四个条件:
① 可分解:原问题可以分解为若干个规模较小的相同子问题。
② 子问题可独立求解:分解出来的子问题可以独立求解,即子问题之间不包含公共的子子问题。
③ 具有分解的终止条件:当问题的规模足够小时,能够用较简单的方法解决。
④ 可合并:子问题的解可以合并为原问题的解,并且合并操作的复杂度不能太高,否则就无法起到减少算法总体复杂度的效果了。
2.4、分治的解题思路
需要用分治算法解决的问题分为三个步骤:
① 分解:把要解决的问题分解为成若干个规模较小、相对独立、与原问题形式相同的子问题。
② 求解:递归求解各个子问题。
③ 合并:按照原问题的要求,将子问题的解逐层合并构成原问题的解。