文章放置于:https://github.com/zgkaii/CS-Notes-Kz,欢迎批评指正!
迭代
迭代(iteration)是重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果。 每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。
利用迭代算法解决问题,需要做好以下三个方面的工作:
- 确定迭代变量
- 建立迭代关系式
- 对迭代过程进行控制
以计算n的阶乘n!
为例,先计算1乘2,然后得到结果再乘以3,在用得到结果乘以4…一直乘到n。用Java代码表示:
public static int factorial(int n) {
int res = 1; // 1.迭代变量
for (int i = 2; i < n; i++) {
// 3.迭代过程进行控制
res *= i; // 2.建立迭代关系式
}
return res;
}
递归
基本概念
程序调用自身的编程技巧称为递归( recursion)。递归算法是一种直接或者间接调用自身函数或者方法的算法,它实质上是把一个大型复杂的原问题拆分成具有相同性质的子问题来求解。
递归至少满足以下两个条件:
- 在过程或函数内调用自身;
- 必须有一个明确的递归终止条件。
还是以阶乘为例,n的阶乘n! = n*(n-1)*... *1 (n>0)
,用Java代码表示:
public static int factorial(int n) {
if (n == 1)
return 1;
return n * factorial(n-1);
}
那么计算5!
时程序的执行过程如下:
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
return 1
return 2*1 = 2
return 3*2 = 6
return 4*6 = 24
return 5*24 = 120
又如裴波拉契(Fibonacci)数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ...,
其递推公式为:F(n) = F(n−1) + F(n−2) 其中(n > 2), F(1) = 1, F(0) = 0
,用Java代码表示:
public static int fibonacci(int n) {
if (n <= 1)
return n;
return fibonacci(n-1) + fibonacci(n-2);
}
以计算fibonacci(5)
为例,一层一层的分解过程画成图,递归树如下:
应用场景
递归应用广泛,除了运用在裴波拉契数列,阶乘,汉诺塔等问题上(可查看Recursion),还用于处理具有天然的递归性的数据结构的问题,例如链表反转、求树的深度等。
写递归代码的关键就是找到如何将大问题分解为小问题的规律,并且基于此写出递推公式,然后再推敲终止条件,最后将递推公式和终止条件翻译成代码。这里有一个思维误区,有人认为要写出递归代码一定要画出完整的递归树,明白每一步递归过程才行。既然递归是一个反复调用自身的过程,这就说明它每一级的功能都是一样的,实际上我们只需要关注一级递归的解决过程即可。
也就是说,在用递归解决问题时,只需关注递归终止条件 与 (当前层)逻辑处理 和 (传递到的下一层)递归调用即可,大致模板如下:
public void recursion(参数0) {
if (终止条件) {
// 必须
return;
}
逻辑