目录
一、汉诺塔
1、什么是汉诺塔?
1.1、汉诺塔由来
法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
1.2、找规律 最少次数 2^n -1
如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。这需要多少次移动呢?这里需要递归的方法。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,找规律推知:(2^n-1)次,递归递推公式f(n)=2*f(n-1)-1。
1.3、最少时间
n=64时,假设每秒钟移动一片,且保证每次移动都是对的,需要多长时间呢?
2^64-1=18446744073709552000次,每年最多336天,每天有24小时,每小时3600秒
18446744073709552000/3600/24=5845.42亿年
2、代码实现 2^n-1
问题:有ABC三根针,针A上有n个金片,怎样才能用最少次数移动到针C上?最少多少次?
核心步骤:
hanoi(n-1,pos1,pos3,pos2); //将在n上面的n-1个通过pos3移到pos2
move(pos1,pos3); //将n移到pos3上hanoi(n-1,pos2,pos1,pos3); //将已在pos2上的n-1通过pos1移到pos3上
//注释中的pos1,pos2,pos3指的是n时候的。因为进入递归后,三者位置会发生改变。
2.1、汉诺塔代码
代码如下(示例):
//汉诺塔
//经过测试得出,n个盘子,至少需要移动2^n-1次
public class Test {
public static void main(String[] args) {
hanoi(1,'A','B','C'); //n=1
System.out.println();
hanoi(2,'A','B','C'); //n=2
System.out.println();
hanoi(3,'A','B','C'); //n=3
}
/**
*
* @param n n个金片
* @param pos1 起始位置
* @param pos2 中转位置
* @param pos3 目标位置
*/
public static void hanoi(int n,char pos1,char pos2,char pos3){
if(n==1){
move(pos1,pos3);
return ; //不能省略,否则会死循环
}
hanoi(n-1,pos1,pos3,pos2);
move(pos1,pos3);
hanoi(n-1,pos2,pos1,pos3);
}
/**
*
* @param start 起始位置
* @param end 目标位置
*/
public static void move(char start,char end){
System.out.print(start+"->"+end+" ");
}
}
效果展示(打印n=1,n=2,n=3):
2.2、分析n=3时
1>、递归详细步骤
2>、整个过程演示
二、青蛙跳台阶
1、什么是青蛙跳台阶?
问题:有n个台阶,一只青蛙要通过台阶。青蛙每次可以跳1、1或2个台阶(2、n个台阶),一共有多少种跳法?
2、代码实现
2.1、一次可以跳1或2级台阶 类似斐波那契数列
理解:
n=1时有一种跳法(一阶一阶跳)
n=2时有两种跳法(一阶一阶跳+跳两阶)
n=3时的方法数=有3种跳法(一阶一阶跳+跳两阶再跳一阶+跳一阶再跳两阶)
再推导几步发现:
分析规律:n=4时青蛙先跳一阶,面对它的还有三个台阶(有三种方法),再跳上去一阶,面对它的还有两级台阶(两种方法),最后剩下两级台阶。
n时方法数是n-1时的方法数+n-2时的方法数
即:f(n)=f(n-1)+f(n-2)
代码如下(示例):
//青蛙跳台阶
//1、一次可以跳1或2级台阶
public class Test {
public static void main(String[] args) {
System.out.println(steps(3));
}
public static int steps(int n){
if (n == 1) {
return 1;
} else if (n==2) {
return 2;
} else if (n>2) {
return steps(n-1)+steps(n-2);
}else{ //n<=0
return 0;
}
}
}
2.2、一次可以跳n级台阶 2^(n-1)
理解:
n=1时,有一种跳法(一阶一阶跳)
n=2时,有两种跳法(一阶一阶跳+跳两阶)
n=3时,有四种跳法(一阶一阶跳+跳两阶再跳一阶+跳一阶再跳两阶+跳三阶)
n=4时,有八种跳法
推导规律:
f(n)=f(n-1)+f(n-2)+f(n-3)...f(2)+f(1)+1;
f(n-1)=f(n-2)+f(n-3)...f(2)+f(1)+1; (带入前面的式子)
所以:f(n)=2*f(n-1) 2^(n-1)种
//青蛙跳台阶
//1、一次可以跳n级台阶
public class Test {
public static void main(String[] args) {
System.out.println(steps(3));
}
public static int steps(int n){
if (n == 1) {
return 1;
} else if (n>1) {
return 2*steps(n-1);
}else{ //n<=0
return 0;
}
}
}