java斐波拉契数列算法_Java与算法之(3) - 斐波那契数列

博客探讨了斐波那契数列的计算问题,从递归方法出发,指出其存在的重复计算导致效率低下。通过引入分治思想的ForkJoinPool实现并行计算优化,但仍然不理想。最后,采用非递归循环方式解决了重复计算的问题,实现了高效的斐波那契数计算。同时提到了斐波那契数列在青蛙跳台阶问题中的应用,展示了其数学规律。
摘要由CSDN通过智能技术生成

斐波那契数列问题:如果一对兔子每月能生1对小兔子,而每对小兔在它出生后的第三个月里,又能开始生1对小兔子,假定在不发生死亡的情况下,由一对初生的兔子开始,1年后能繁殖出多少对兔子?

首先手工计算来总结规律,如下表

c3db5afdfbb247713cef3ec1b10d0906.png

注意总数这一列

1+1=2

1+2=3

2+3=5

3+5=8

5+8=13

可以得出规律,第n个斐波那契数=第n-1个斐波那契数+第n-2个斐波那契数

为了计算n,必须计算n-1和n-2;为了计算n-1,必须计算n-2和n-3;直到n-x的值为1为止,这显示是递归大显身手的地方。来看代码

public class Fibonacci {

public static long calc(long n) {

if(n 

return 0;

}

if(n == 0 || n == 1) {

return n;

} else {

return calc(n - 1) + calc(n - 2);

}

}

}

这真是极短的,测试代码

public static void main(String[] args) {

long n = 50;

long begin = System.nanoTime();

long f = Fibonacci.calc(n);

long end = System.nanoTime();

System.out.println("第" + n + "个斐波那契数是" + f + ", 耗时" + TimeUnit.NANOSECONDS.toMillis(end - begin) + "毫秒");

}

运行输出

第50个斐波那契数是12586269025, 耗时66024毫秒

注意看消耗的时间,在我的电脑上耗时66秒,真是个相当耗时的操作。既然整个过程都是在不断重复相同的计算规则,那我们可以采用分而治之的思想来优化代码。

import java.util.concurrent.ForkJoinPool;

import java.util.concurrent.RecursiveTask;

import java.util.concurrent.TimeUnit;

public class Fibonacci extends RecursiveTask {

long n;

public Fibonacci(long n) {

this.n = n;

}

public Long compute() {

if(n <= 10) {  //小于10不再分解

return Fibonacci.calc(n);

}

Fibonacci f1 = new Fibonacci(n - 1);  //分解出计算n-1斐波那契数的子任务

f1.fork();  //由ForkJoinPool分配线程执行子任务

Fibonacci f2 = new Fibonacci(n - 2);  //分解出计算n-2斐波那契数的子任务

return f2.compute() + f1.join();

}

public static long calc(long n) {

if(n 

return 0;

}

if(n == 0 || n == 1) {

return n;

} else {

return calc(n - 1) + calc(n - 2);

}

}

public static void main(String[] args) {

long n = 50;

long begin = System.nanoTime();

Fibonacci fibonacci = new Fibonacci(n);

ForkJoinPool pool = new ForkJoinPool();

long f = pool.invoke(fibonacci);

long end = System.nanoTime();

System.out.println("第" + n + "个斐波那契数是" + f + ", 耗时" + TimeUnit.NANOSECONDS.toMillis(end - begin) + "毫秒");

}

}

运行输出

第50个斐波那契数是12586269025, 耗时20461毫秒

虽然时间缩短了2/3,但是仍然不理想。回头重新看计算方法,用递归方式虽然代码简短,但是存在很严重的重复计算,下面用非递归的方式改写,过程中每个数只计算一次。

public static long calcWithoutRecursion(long n) {

if(n 

return 0;

if(n == 0 || n == 1) {

return n;

}

long fib = 0;

long fibOne = 1;

long fibTwo = 1;

for(long i = 2; i 

fib = fibOne + fibTwo;

fibTwo = fibOne;

fibOne = fib;

}

return fib;

}

测试

第50个斐波那契数是12586269025, 耗时0毫秒

斐波那契数的另一个经典题目是青蛙跳台阶问题:

一只青蛙一次可以条一级或两级台阶,求该青蛙跳上n级的台阶共有多少种跳法。

假设计算第n级台阶跳法的函数是f(n),当n>2时,第一步选择跳一级有X种跳法,第一步选择跳两级有Y种跳法,f(n)=X+Y。如何计算X呢,站在青蛙的位置考虑,面对的是一个全新的n-1级台阶,有f(n-1)种跳法,那么Y就是n-2级台阶的跳法,那么f(n)=f(n-1)+f(n-2),即斐波那契数列公式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值