递归算法
什么是递归
定义:递归算法是一种直接或者间接调用自身函数或者方法的算法。
通俗来说,递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。它有如下特点:
- 一个问题的解可以分解为几个子问题的解
- 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
- 存在递归终止条件,即必须有一个明确的递归结束条件,称之为递归出口
应用递归算法解决的几个例子:
斐波那契兔子繁殖问题
已知一对兔子每一个月可以生一对小兔子,而一对兔子出生后第二个月就开始生小兔子。假如一年内没有发生死亡,则一对兔子一年内能繁殖成多少对?
一年后可以繁殖成多少对兔子?假定每对大兔每月能生产一对小兔,而每对小兔生长两个月就成为大兔.这个问题导致了著名的数列:1,1,2,3,5,8,13,21,34,55,89,144,233,·…它是一个线性递归数列,.这个数列一般称为斐波那契数列,它的每一项称为斐波那契数
用递归算法实现代码如下:
package 方法的定义;
public class LY16斐波那契兔子问题 {
static int f(int a) {
int z;
if (a == 1 | a == 2) {
z = 1;
} else {
z = f(a - 1) + f(a - 2);
}
return z;
}
public static void main(String[] args) {
int a;
a = f(12);
System.out.println(a);
}
}
运行结果为144
求一个数的阶乘
这个是我写的20的阶乘
用递归算法实现代码如下:
package 方法的定义;
public class LY17阶乘 {
static int jiecheng(int n) {
int a = 1;
if (n == 1) {
a = 1;
} else {
a = n * jiecheng(n - 1);
}
return a;
}
public static void main(String[] args) {
long n;
n = jiecheng(5);
System.out.println(n);
}
}
运行结果为120
汉诺塔问题
汉诺塔问题:古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。一次只能移动一个磁盘,不能在较小的磁盘上放置较大的磁盘。
① 如果只有 1 个盘子,则不需要利用 B 塔,直接将盘子从 A 移动到 C 。
② 如果有 2 个盘子,可以先将盘子 2 上的盘子 1 移动到 B ;将盘子 2 移动到 C ;将盘子 1 移动到 C 。这说明了:可以借助 B 将 2 个盘子从 A 移动到 C ,当然,也可以借助 C 将 2 个盘子从 A 移动到 B 。
③ 如果有 3 个盘子,那么根据 2 个盘子的结论,可以借助 C 将盘子 3 上的两个盘子从 A 移动到 B ;将盘子 3 从 A 移动到 C ,A 变成空座;借助 A 座,将 B 上的两个盘子移动到 C 。
④ 以此类推,上述的思路可以一直扩展到 n 个盘子的情况,将将较小的 n-1个盘子看做一个整体,也就是我们要求的子问题,以借助 B 塔为例,可以借助空塔 B 将盘子A上面的 n-1 个盘子从 A 移动到 B ;将A 最大的盘子移动到 C , A 变成空塔;借助空塔 A ,将 B 塔上的 n-2 个盘子移动到 A,将 C 最大的盘子移动到 C, B 变成空塔。
用递归算法实现代码如下:
package 方法的定义;
public class LY15汉诺塔 {
static void hanoi(int n, char A, char B, char C) {
if (n == 1) {
System.out.println("move:" + n + A + "--->" + C);
} else {
hanoi(n - 1, A, C, B);
System.out.println("move:" + n + A + "--->" + C);
hanoi(n - 1, B, A, C);
}
}
public static void main(String[] args) {
System.out.println("移动汉诺塔的步骤:");
hanoi(2, 'a', 'b', 'c');
}
}
运行结果为:
移动汉诺塔的步骤:
move:1a—>b
move:2a—>c
move:1b—>c