☀️前言☀️
本篇文章给大家讲解递归入门的经典习题之求斐波那契数列、青蛙跳台阶、汉诺塔。
👦有缘,才相遇,你好!我是hgway_hxz
❤️热爱Java,希望结识更多的小伙伴一起交流
🎉欢迎大家:👍点赞 💬评论 ⭐收藏 💖关注
✉️如果有任何问题欢迎大家在评论区讨论或者私信我
✏️只要敢于拼搏,失败也是一种欣慰
🔓1.求斐波那契数列的第 N 项
**斐波那契数列**指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89…这个数列从第3项开始,每一项都等于前两项之和。
💡解题思路:
我们用递归做,先找出
递归条件:fib(n) = fib(n - 2) + fib(n - 1) (n > 2)
终止条件:n == 1 || n == 2
🔑代码:
public static int fib(int n) {
if (n == 2 || n == 1) {
return 1;
}
return fib(n - 2) + fib(n - 1);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(fib(n));
}
如果n的值过大的话,可能会产生过多的冗余计算,浪费计算资源,所以可以用循环迭代做:
代码:
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
int f1 = 1;
int f2 = 1;
int f3 = 0;
for (int i = 3; i <= n; i++) {
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
return f3;
}
🔓2.青蛙跳台阶问题
💡解题思路:
(提示, 使用递归) 一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法,跟上题的求斐波那契数列的第 N 项想法一样,类似题目:BC166 小乐乐走台阶
n = 1时, 1种跳法
n = 2时, 2种跳法
n = 3时, 3种跳法 等于前两项之和
n = 4时, 5种跳法
…………
使用递归
我们用递归做,先找出
递归条件:frogJump(n) = frogJump(n - 2) +frogJump(n - 1) (n > 1)
终止条件:n == 1 || n == 2
🔑递归代码:
public static int frogJump(int n) {
if (n == 1 || n == 2) {
return n;
}
return frogJump(n - 1) + frogJump(n - 2);
}
🔑循环代码:
public static int frogJump(int n) {
if (n == 1 || n == 2) {
return n;
}
int f1 = 1;
int f2 = 2;
int f3 = 0;
for (int i = 3; i <= n; i++) {
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
return f3;
}
🔓3.求解汉诺塔问题
汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。 大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。 并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。 问应该如何操作?
💡解题思路:
有A、B、C三个柱子,我们需要把A柱上的若干个盘子从A柱按照上小下大的顺序移动到C柱上,一次只能移动一个盘子,从上到下盘子的编号为1~n。
当盘子的个数n为1时,盘子从A柱移动到C柱
n = 1,A -> C
当盘子的个数n为2时,盘子从A柱移动到B柱,A柱移动到C柱,B柱移动到C柱
n = 2,A -> B,A -> C,B -> C
当盘子的个数n为3时,盘子从A柱移动到C柱,A柱移动到B柱,C柱移动到B柱,A柱移动到C柱,B柱移动到A柱,B柱移动到C柱,A柱移动到C柱
n = 3,A -> C,A -> B,C -> B,A -> C,B -> A,B -> C,A -> C
…………
我们发现以下规律:
- n = 1时,把盘子从A柱移动到C柱
- n > 1时,把n - 1个盘子从A柱全部移动到B柱,然后盘子A柱移动到C柱
- 把n - 1个盘子从B柱全部移动到C柱
🔑代码:
/**
* 盘子从pos1位置移动到pos2位置
* @param n 盘子的个数
* @param pos1 盘子的起始位置
* @param pos2 盘子的结束位置
*/
public static void move(int n, char pos1, char pos2) {
System.out.print(pos1 + "->" + pos2 + " ");
}
/**
*
* @param n 盘子的个数
* @param pos1 盘子的起始位置
* @param pos2 盘子的中转位置
* @param pos3 盘子的结束位置
*/
public static void hanoi(int n, char pos1, char pos2, char pos3) {
if (n == 1) {
move(1, pos1, pos3);
} else {
hanoi(n - 1, pos1, pos3, pos2);
move(1, pos1, pos3);
hanoi(n - 1, pos2, pos1, pos3);
}
}
public static void main(String[] args) {
hanoi(1, 'A', 'B', 'C');
System.out.println();
hanoi(2, 'A', 'B', 'C');
System.out.println();
hanoi(3, 'A', 'B', 'C');
}
结果:
A->C
A->B A->C B->C
A->C A->B C->B A->C B->A B->C A->C
Process finished with exit code 0