第0项为0,第1项为1,第2项为1,第3项为2…后面的项是之前两项的和。
这种后面的内容恰好需要前面的值得让人一下就想到了递归。
public static int fibonacci(int n) {
if(n == 0){
return 0;
}else if(n == 1||n==2){
return 1;
}else return (fibonacci(n-1)+fibonacci(n-2));
}
再暴力一点!
public static int fibonacci(int n) {
(n<2)? return n : return (fibonacci(n-1)+fibonacci(n-2));
}
看似简便但是对于fibonacci(n-1)和fibonacci(n-2)来说每个都要单独递归一遍实在很麻烦。而且数字一大还会产生栈溢出的现象。解决的办法就是用空间换时间改成用数组去记忆之前所运算的值:
public static int fibonacci1(int n){
int[] arr = new int[n+1];
arr[0] = 0;arr[1]=1;
for(int i = 2;i<=n+1;i++){
arr[i]=arr[i-1]+arr[i-2];
}
return arr[n+1];
}
其实用迭代的思路也能实现记忆功能(动态规划)//其实只需要两个变量我这里写麻烦了
public static int fibonacci2(int n){
if(n<=1){return n;}
int fibonacci1 = 0,feibonacci2=1,feibonacci3 =0;
for(int i = 2;i<=n;i++){
feibonacci3 = fibonacci1 + feibonacci2;
fibonacci1 = feibonacci2;
feibonacci2 = feibonacci3;
}
return feibonacci3;
}
但是数据一大这就出现了毛病,我无法求第50项的值。换成long?可是再超过范围了又该怎么办??
这里就需要用到大数计算
public static BigInteger fibonacci3(int n) {
if(n == 0){
return BigInteger.valueOf(0);
}else if(n==1 ){
return BigInteger.valueOf(1);
}else return fibonacci3(n-1).add(fibonacci3(n-2));
}
BigInteger a = new BigInteger(“1”);//构造a.add(b)//相加subtract();// 相减multiply(); //相乘divide(); //相除取整remainder();// 取余
这是斐波那契第50项的值,下面一行是所用时间,10分多钟吧。不得不说是真的卡。。。但是总算是算出来了。
好吧50项都十分钟了那51项还不得20多分钟???所以就需要用到矩阵的思想去解决。
奈何我数学不好,以后有机会再填这个坑。
斐波那契的思想还可以解决变态上楼梯的问题。一只青蛙每次可以上一阶或者两阶台阶。有n阶台阶请问有多少种方法?
不用递归的思想解决如下所示
public static int jump(int n) {
//首先求出最多有多少次跳偶数阶台阶
int evenMix = n / 2;
//下来思考在一堆1里面插入0个2乃至n/2个分别有多少种办法最后求和
int sum = 0;
for (int i = 0; i <= evenMix; i++) {//i 本次2阶的个数,
int count = n - i;//跳本次总jump数
sum = sum + factorial(count)/factorial(count-i)/factorial(i);
}return sum;
}
public static int factorial(int n) {
int sum = 1;
while (n > 0) {
sum = sum * n--;
}
return sum;
}
运用递归
求n阶有多少种可能,最后一步无非就只可能跳1阶或者2阶,最后跳1阶的可能即n-1阶台阶的所有可能,最后跳2阶的可能即跳n-2阶台阶的所有可能。故n阶即为两者之和。恰好满足斐波那契数列。
该问题等价于有2n大小的矩形,用21大小的矩形去填请问共有多少种填法。
斐波那契还是原来的斐波那契,青蛙却已经不是原来的青蛙了。
现在青蛙升级了每次可以跳1~n个台阶,请问n个台阶共有多少种方法。
还是通过最后一步分析,最后一步可以1~n阶
最后1阶时 方法等于n-1阶
最后2阶时 方法等于n-2阶
…
最后n阶时 方法等于n-n阶//跳0阶时次数为1
代码如下:
public static int jumpplus(int n){
int sum = 0;
if(n<2){return1;}
else {
for(int i=1;i<=n;i++)
sum+=jump(n-1);
}
return sum;
}
其实这样写还是麻烦了很多,更好的做法是先通过逻辑进行优化
jump(n)=jump(n-1)+jump(n-2)+…+jump(0);
jump(n-1)=jump(n-2)+jump(n-3)…+jump(0);
故jump(n)=2*jump(n-1);