一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶,求该青蛙跳上一个n级的台阶总共需要多少种跳法。
当n等于1的时候,只需要跳一次即可,只有一种跳法,记f(1)=1;
当n等于2的时候,可以先跳一级再跳一级,或者直接跳二级,共有2种跳法,记f(2)=2;
当n等于3的时候,他可以从一级台阶上跳两步上来,也可以从二级台阶上跳一步上来,所以总共有f(3)=f(2)+f(1);
当n等于n的时候,总共有f(n)=f(n-1)+f(n-2)(这里n>2)种跳法。
public static int f(int n){
if(n<=0){
return 0;
}
if(n==1){
return 1;
}
if(n==2){
return 2;
}
return f(n-1)+f(n-2);
}
计算f(6):
递归会重复计算已经计算过的值,效率明显不是很高,所以可以把计算过的值储存起来,防止重复计算。
public class JumpFrog {
public static int f2(int n, HashMap<Integer,Integer> map){
if(n<=0){
return 0;
}
if(n==1){
return 1;
}
if(n==2){
return 2;
}
if(map.containsKey(n)){
return map.get(n);
}
int first=f2(n-1,map);
int second=f2(n-2,map);
int sum=first+second;
map.put(n,sum);
return sum;
}
// 非递归方法
public static int f3(int n){
if(n<=0){
return 0;
}
if(n==1){
return 1;
}
if(n==2){
return 2;
}
int first=1,second=2,sum=0;
while(n-- > 2){
sum=first+second;
first=second;
second=sum;
}
return sum;
}
}
变态跳台阶:一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶……,也可以跳n级,求该青蛙跳上一个n级的台阶总共需要多少种跳法。
递推格式:
f(n)=f(n-1)+f(n-2)+……+f(2)+f(1);
f(n-1)=f(n-2)+f(n-3)+……+f(2)+f(1);
所以得出:f(n)=f(n-1)+f(n-1)=2*f(n-1),且f(1)=1。
private static int f4(int n){
if(n==1){
return 1;
}
return f4(n-1)*2;
}
private static int f5(int n){
if(n==1){
return 1;
}
return 1<<(n-1);
}
进阶二:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上m级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
分开讨论:
1,如果 n<=m;因为只能往上跳不能往下跳,所以大于n的都不可以跳,如果跳了就直接超过了,只能跳小于等于n的数字,那么这个问题就直接退到问题2了。
2,如果 n>m;我们要想跳到n级台阶,我们可以从n-1级跳一步上来,或者从n-2级跳两步上来,或者从n-m级跳m步上来,
所以得到地推公式: f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-m);
进一步可以推出:f(n-1) = f(n-2) + f(n-3) + ... + f(n-m) + f(n-m-1);
化简结果为:f(n) = 2f(n-1) - f(n-m-1);(n>m)
public static int f6(int n,int m){
if(n<=1){
return 1;
}
// 总台阶大于跳的最高级台阶
if(n>m){
return 2*f6(n-1,m)-f6(n-1-m,m);
}
return 2*f6(n-1,n);
}