斐波那契数列:0、1、1、2、3、5、8、13…………

他的规律是,第一项是0,第二项是1,第三项开始(含第三项)等于前两项之和。

> 递归实现

看到这个规则,第一个想起当然是递归算法去实现了,于是写了以下一段:

public class RecursionForFibonacciSequence {

    public static void main(String[] args) {
System.out.println(recursion(10));
} public static double recursion(double i) {
if (i == 0) {
printResult(i, 0);
return 0;
}
if (i == 1) {
printResult(i, 1);
return 1;
} double result = recursion(i - 1) + recursion(i - 2);
printResult(i, result); return result;
} /**
* 打印结果
*/
public static void printResult(double i, double result) {
System.out.println(i + " -> " + result);
} }

它能正常运行,比如计算第10项的结果为55。

但是,计算数字大点的数据,则很慢很慢,因为重复计算太多了。

日志:

1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
6.0 -> 8.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
7.0 -> 13.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
6.0 -> 8.0
8.0 -> 21.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
6.0 -> 8.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
7.0 -> 13.0
9.0 -> 34.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
6.0 -> 8.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
7.0 -> 13.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
5.0 -> 5.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
4.0 -> 3.0
6.0 -> 8.0
8.0 -> 21.0
10.0 -> 55.0
55.0

> 递归值缓存实现

用最直观的方式优化,既然重复计算太多了,而重复计算的结果都是一样的,那么我们就将重复计算的结果集缓存起来吧。

因为上例的递归效率低,不能执行太多的项数,所以只执行到10,而下面这个写法的效率大为提高,所以我们执行到100看看。

import java.util.HashMap;
import java.util.Map; public class CacheForFibonacciSequence { public static void main(String[] args) {
System.out.println(recursion(100));
} // 缓存计算结果集
public static Map<Double, Double> map = new HashMap<Double, Double>(); public static double recursion(double i) {
if (i == 0) {
printResult(i, 0);
return 0;
}
if (i == 1) {
printResult(i, 1);
return 1;
} if (map.containsKey(i)) {
return map.get(i);
} double result = recursion(i - 1) + recursion(i - 2);
printResult(i, result);
map.put(i, result); return result;
} /**
* 打印结果
*/
public static void printResult(double i, double result) {
System.out.println(i + " -> " + result);
} }

日志:

1.0 -> 1.0
0.0 -> 0.0
2.0 -> 1.0
1.0 -> 1.0
3.0 -> 2.0
4.0 -> 3.0
5.0 -> 5.0
6.0 -> 8.0
7.0 -> 13.0
8.0 -> 21.0
9.0 -> 34.0
10.0 -> 55.0
11.0 -> 89.0
12.0 -> 144.0
13.0 -> 233.0
14.0 -> 377.0
15.0 -> 610.0
16.0 -> 987.0
17.0 -> 1597.0
18.0 -> 2584.0
19.0 -> 4181.0
20.0 -> 6765.0
21.0 -> 10946.0
22.0 -> 17711.0
23.0 -> 28657.0
24.0 -> 46368.0
25.0 -> 75025.0
26.0 -> 121393.0
27.0 -> 196418.0
28.0 -> 317811.0
29.0 -> 514229.0
30.0 -> 832040.0
31.0 -> 1346269.0
32.0 -> 2178309.0
33.0 -> 3524578.0
34.0 -> 5702887.0
35.0 -> 9227465.0
36.0 -> 1.4930352E7
37.0 -> 2.4157817E7
38.0 -> 3.9088169E7
39.0 -> 6.3245986E7
40.0 -> 1.02334155E8
41.0 -> 1.65580141E8
42.0 -> 2.67914296E8
43.0 -> 4.33494437E8
44.0 -> 7.01408733E8
45.0 -> 1.13490317E9
46.0 -> 1.836311903E9
47.0 -> 2.971215073E9
48.0 -> 4.807526976E9
49.0 -> 7.778742049E9
50.0 -> 1.2586269025E10
51.0 -> 2.0365011074E10
52.0 -> 3.2951280099E10
53.0 -> 5.3316291173E10
54.0 -> 8.6267571272E10
55.0 -> 1.39583862445E11
56.0 -> 2.25851433717E11
57.0 -> 3.65435296162E11
58.0 -> 5.91286729879E11
59.0 -> 9.56722026041E11
60.0 -> 1.54800875592E12
61.0 -> 2.504730781961E12
62.0 -> 4.052739537881E12
63.0 -> 6.557470319842E12
64.0 -> 1.0610209857723E13
65.0 -> 1.7167680177565E13
66.0 -> 2.7777890035288E13
67.0 -> 4.4945570212853E13
68.0 -> 7.2723460248141E13
69.0 -> 1.17669030460994E14
70.0 -> 1.90392490709135E14
71.0 -> 3.08061521170129E14
72.0 -> 4.98454011879264E14
73.0 -> 8.06515533049393E14
74.0 -> 1.304969544928657E15
75.0 -> 2.11148507797805E15
76.0 -> 3.416454622906707E15
77.0 -> 5.527939700884757E15
78.0 -> 8.944394323791464E15
79.0 -> 1.447233402467622E16
80.0 -> 2.3416728348467684E16
81.0 -> 3.7889062373143904E16
82.0 -> 6.1305790721611584E16
83.0 -> 9.9194853094755488E16
84.0 -> 1.60500643816367072E17
85.0 -> 2.5969549691112256E17
86.0 -> 4.2019614072748966E17
87.0 -> 6.7989163763861222E17
88.0 -> 1.10008777836610189E18
89.0 -> 1.77997941600471398E18
90.0 -> 2.880067194370816E18
91.0 -> 4.6600466103755305E18
92.0 -> 7.5401138047463465E18
93.0 -> 1.2200160415121877E19
94.0 -> 1.9740274219868226E19
95.0 -> 3.19404346349901E19
96.0 -> 5.168070885485833E19
97.0 -> 8.362114348984843E19
98.0 -> 1.3530185234470676E20
99.0 -> 2.189229958345552E20
100.0 -> 3.54224848179262E20
3.54224848179262E20

> 循环方式

还有我们也可以用循环的方式,只用两个变量缓存前两项的值:

public class ForeachForFibonacciSequence {

    public static void main(String[] args) {
System.out.println(foreach(100));
} public static double foreach(double i) {
if (i <= 0d) {
return 0d;
} if (i == 1d) {
return 1d;
} double temp1 = 0d;
double temp2 = 1d;
double tempSum = 0;
for (double d = 2; d <= i; d++) {
tempSum = temp1 + temp2;
printResult(d, tempSum); temp1 = temp2;
temp2 = tempSum;
} return tempSum;
} /**
* 打印结果
*/
public static void printResult(double i, double result) {
System.out.println(i + " -> " + result);
} }

日志:

2.0 -> 1.0
3.0 -> 2.0
4.0 -> 3.0
5.0 -> 5.0
6.0 -> 8.0
7.0 -> 13.0
8.0 -> 21.0
9.0 -> 34.0
10.0 -> 55.0
11.0 -> 89.0
12.0 -> 144.0
13.0 -> 233.0
14.0 -> 377.0
15.0 -> 610.0
16.0 -> 987.0
17.0 -> 1597.0
18.0 -> 2584.0
19.0 -> 4181.0
20.0 -> 6765.0
21.0 -> 10946.0
22.0 -> 17711.0
23.0 -> 28657.0
24.0 -> 46368.0
25.0 -> 75025.0
26.0 -> 121393.0
27.0 -> 196418.0
28.0 -> 317811.0
29.0 -> 514229.0
30.0 -> 832040.0
31.0 -> 1346269.0
32.0 -> 2178309.0
33.0 -> 3524578.0
34.0 -> 5702887.0
35.0 -> 9227465.0
36.0 -> 1.4930352E7
37.0 -> 2.4157817E7
38.0 -> 3.9088169E7
39.0 -> 6.3245986E7
40.0 -> 1.02334155E8
41.0 -> 1.65580141E8
42.0 -> 2.67914296E8
43.0 -> 4.33494437E8
44.0 -> 7.01408733E8
45.0 -> 1.13490317E9
46.0 -> 1.836311903E9
47.0 -> 2.971215073E9
48.0 -> 4.807526976E9
49.0 -> 7.778742049E9
50.0 -> 1.2586269025E10
51.0 -> 2.0365011074E10
52.0 -> 3.2951280099E10
53.0 -> 5.3316291173E10
54.0 -> 8.6267571272E10
55.0 -> 1.39583862445E11
56.0 -> 2.25851433717E11
57.0 -> 3.65435296162E11
58.0 -> 5.91286729879E11
59.0 -> 9.56722026041E11
60.0 -> 1.54800875592E12
61.0 -> 2.504730781961E12
62.0 -> 4.052739537881E12
63.0 -> 6.557470319842E12
64.0 -> 1.0610209857723E13
65.0 -> 1.7167680177565E13
66.0 -> 2.7777890035288E13
67.0 -> 4.4945570212853E13
68.0 -> 7.2723460248141E13
69.0 -> 1.17669030460994E14
70.0 -> 1.90392490709135E14
71.0 -> 3.08061521170129E14
72.0 -> 4.98454011879264E14
73.0 -> 8.06515533049393E14
74.0 -> 1.304969544928657E15
75.0 -> 2.11148507797805E15
76.0 -> 3.416454622906707E15
77.0 -> 5.527939700884757E15
78.0 -> 8.944394323791464E15
79.0 -> 1.447233402467622E16
80.0 -> 2.3416728348467684E16
81.0 -> 3.7889062373143904E16
82.0 -> 6.1305790721611584E16
83.0 -> 9.9194853094755488E16
84.0 -> 1.60500643816367072E17
85.0 -> 2.5969549691112256E17
86.0 -> 4.2019614072748966E17
87.0 -> 6.7989163763861222E17
88.0 -> 1.10008777836610189E18
89.0 -> 1.77997941600471398E18
90.0 -> 2.880067194370816E18
91.0 -> 4.6600466103755305E18
92.0 -> 7.5401138047463465E18
93.0 -> 1.2200160415121877E19
94.0 -> 1.9740274219868226E19
95.0 -> 3.19404346349901E19
96.0 -> 5.168070885485833E19
97.0 -> 8.362114348984843E19
98.0 -> 1.3530185234470676E20
99.0 -> 2.189229958345552E20
100.0 -> 3.54224848179262E20
3.54224848179262E20

> 尾递归方式

从回复的网友“Mr_listening”的博文中了解到,还可以用尾递归的方式实现,看以下代码:

public class RecursionTailForFibonacciSequence {

    public static void main(String[] args) {
System.out.println(recursionTail(10, 1, 1));
} public static double recursionTail(int i, double temp1, double temp2) {
if (i < 2) {
return temp1;
} double result = recursionTail(i - 1, temp2, temp1 + temp2);
printResult(i - 1, temp2, temp1 + temp2, result);
return result;
} /**
* 打印结果
*/
public static void printResult(double i, double temp1, double temp2, double result) {
System.out.println("recursionTail(" + i + ", " + temp1 + ", " + temp2 + ") -> " + result);
} }

日志:

recursionTail(1.0, 55.0, 89.0) -> 55.0
recursionTail(2.0, 34.0, 55.0) -> 55.0
recursionTail(3.0, 21.0, 34.0) -> 55.0
recursionTail(4.0, 13.0, 21.0) -> 55.0
recursionTail(5.0, 8.0, 13.0) -> 55.0
recursionTail(6.0, 5.0, 8.0) -> 55.0
recursionTail(7.0, 3.0, 5.0) -> 55.0
recursionTail(8.0, 2.0, 3.0) -> 55.0
recursionTail(9.0, 1.0, 2.0) -> 55.0
55.0

【Java】斐波那契数列(Fibonacci Sequence、兔子数列)的3种计算方法(递归实现、递归值缓存实现、循环实现、尾递归实现)的更多相关文章

  1. 第2章 数字之魅——斐波那契(Fibonacci)数列

    斐波那契(Fibonacci)数列 问题描述 递归算法: package chapter2shuzizhimei.fibonacci; /** * Fibonacci数列递归求解 * @author ...

  2. 斐波那契堆(Fibonacci heap)原理详解(附java代码实现)

    前言 斐波那契堆(Fibonacci heap)是计算机科学中最小堆有序树的集合.它和二项式堆有类似的性质,但比二项式堆有更好的均摊时间.堆的名字来源于斐波那契数,它常用于分析运行时间. 堆结构介绍 ...

  3. java斐波那契数列的顺序输出

    斐波那契数列,即1.1.2.3.5......,从第三个数开始包括第三个数,都为这个数的前两个数之和,而第一第二个数都为1. 下面是java输出斐波那契数列的代码: import java.util. ...

  4. python - 斐波那契(Fibonacci)数列

    斐波那契数列即数列中每一项等于它前面两项的和,公式如下: f(n) = f(n-1) + f(n-2)    n>2        -----        递推公式 f(n) = 1     ...

  5. java斐波纳契数列

    //斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.-- 这个数列从第三项开始,每一项都等于前两项之和. public class DiGui { public ...

  6. [Swift]LeetCode509. 斐波那契数 | Fibonacci Number

    The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such th ...

  7. 20190803 NOIP模拟测试12「斐波那契(fibonacci)· 数颜色 · 分组 」

    164分 rank11/64 这次考的不算太差,但是并没有多大的可能性反超(只比一小部分人高十几分而已),时间分配还是不均,T2两个半小时,T1半个小时,T3-额十几分钟吧 然额付出总是与回报成反比的 ...

  8. Java版经典兔子繁殖迭代问题——斐波那契(Fibonacci)数列

    /** * 题目: * 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子. * 假如兔子都不死,问经过month个月后,兔子的总数为多少对? */ public ...

  9. 打印斐波那契(Fibonacci)数列

    需求:打印 Fibonacci数列 思路: 当前项的值等于前两项数值的和 F=(F-1)+F(F-2) 样例: 输入:10 输出:1 1 2 3 5 8 13 21 34 55 辗转相加法实现 #in ...

  10. java 斐波那契数列

    package feibo; public class Feibo { static int ss = 50; public static void main(String[] args) { // ...

随机推荐

  1. 【皇甫】☀亲爱的~help me

     亲爱的,我不知道该怎么把我想对你说的话表达出来,希望我对你的认识真的像下面的内容一样,如果我有错,那说明我还不够了解你... 希望我们能够一起走到最后吧... 首先,说说最近的吧,  在我还没有和你 ...

  2. (转)【ASP.NET开发】获取客户端IP地址 via C#

    [ASP.NET开发]获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己 ...

  3. paper 73 :HDR(High Dynamic Range Imaging)在摄影中指高动态范围成像

    HDR(High Dynamic Range Imaging)在摄影中指高动态范围成像.国内的教程基本语焉不详,找到一篇比较详尽的国外教程翻译出来,希望对大家有帮助.^_^ 原文地址:http://p ...

  4. opengl& 颜色

    颜色 简介 颜色的显示模式分为两种: RGBA显示模式 颜色索引显示模式(使用颜色映射表,映射表提供了索引,可以混合基本的红,绿,蓝色值). RGBA模式可以选择的颜色数量多于颜色索引模式.一般而言, ...

  5. access调用联系

    using System; using System.Configuration; using System.Data; using System.Linq; using System.Web; us ...

  6. 【rails3教材】博客构建过程2

    2. 使用脚手架快速搭建网页 rails的脚手架可以快速生成应用程序的一些片段,如果你需要为一个资源创建一系列的控制器视图模型,那么脚手架就是你需要的工具 3. 创建资源 对于一个博客程序,你可以以生 ...

  7. 七、Java基础---------JDK安装与配置

    配置环境变量名词说明 path:通过path系统去寻找可执行的java文件. JAVA_HOME:JDK的安装目录 classpath:加载目录 为什么需要配置path,什么时候需要classpath ...

  8. ubuntu支持shh远程连接记录

    打开终端输入sudo apt-get update更新软件库 在输入sudo apt-get install openssh-server下载ssh sudo /etc/init.d/ssh rest ...

  9. resultMap / resultType

    ===================resultMap:实体类的属性和通过resultMap映射后的property属性一致 <resultMap id="workerSelect& ...

  10. JSP中文乱码问题解决方法小结

    在使用JSP的过程中,最使人头疼的一个问题就是中文乱码问题,以下是我在软件开发中遇到的乱 码问题以及解决方法. 1.JSP页面乱码 这种乱码的原因是应为没有在页面里指定使用的字符集编码,解决方法:只要 ...