一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
解题思路:
这其实是一个斐波那契数列,可以用递归的方式来接替。
F(n)=F(n-1)+F(n-2) F(n-1)等于青蛙跳了1个台阶之后剩余的可能,F(n-2)等于青蛙跳了2个台阶之后剩余的可能。
当然,递归运算运算的次数指数型增长,当N比较大时,有可能会导致stackoverflow。
所以这里暂且换一种思路。
架设N=6,则分为4种可能性,跳2级的次数分别为0,1,2,3。然后
0:1种可能
1:5种可能
2:6种可能
3:1种可能
最终求和就得到13。
每种可能,其实可以理解为n个白球,m个黑球,有多少种排列组合。k=m+n,n>m,如下图:
public static void main(String[] args) {
Solution solution = new Solution();
int fibonacci = solution.JumpFloor(29);
System.out.println(fibonacci);
}
public int JumpFloor(int target) {
if (target == 1) {
return 1;
}
int count = 0;
int num1 = 0;
for (int num2 = 0; num2 * 2 <= target; num2++) {
num1 = target - num2 * 2;
long num = getNum(num1, num2);
count += num;
}
return count;
}
//num1个黑球,num2个白球,有多少种排列组合 架设num1+num2=num,共有(A num num)/(A num1 num1)/(A num2 num2)种可能
public long getNum(int num1, int num2) {
long count = 1;
int num = num1 + num2;
if (num1 == 0 || num2 == 0) {
return count;
}
if (num1 > num2) {
while (num > num1) {
count = count * num;
num--;
}
while (num2 > 1) {
count = count / num2;
num2--;
}
} else {
while (num > num2) {
count = count * num;
num--;
}
while (num1 > 1) {
count = count / num1;
num1--;
}
}
if (count < 0) {
System.out.println("num1:" + num1);
}
return count;
}
当然,这里存在一个问题,就是如果N过大的话,会导致long型也会溢出。所以这种解法也不是最好的,后续在想。
第二种解法,递归。其实就是我上面说的那种,但是我们可以换个思路,把结果缓存下来,那么就不需要多次运算了。也解决stackoverflow的问题。
代码如下:
import java.util.HashMap;
public class Solution {
HashMap<Integer, Integer> cache = new HashMap<>();
public static void main(String[] args) {
Solution solution = new Solution();
int i = solution.JumpFloor(4);
System.out.println(i);
}
public int JumpFloor(int target) {
if (target == 0) {
return 0;
}
Integer cacheInt = cache.get(target);
if (cacheInt != null) {
return cacheInt;
}
if (target == 1) {
return 1;
}
if (target == 2) {
return 1;
}
int i1 = JumpFloor(target - 1);
int i2 = JumpFloor(target - 2);
int count = i1 + i2;
cache.put(target, count);
return count;
}
}