斐波纳契函数java实现的误区--谨慎使用递归
2013-02-21 10:11
211 查看
最近在研究算法,遇到了斐波纳契函数,即1,2,3,5,8,13,21,34,55,89,...,通用式为:f(n)=f(n-1)+f(n-2).
在数学上,费波那西数列是以递归的方法来定义:
用文字来说,就是费波那西数列由 0 和 1 开始,之后的费波那西系数就由之前的两数相加。首几个费波那西系数是(OEIS A000045):
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,………………
特别指出:0不是第一项,而是第零项。
摘自维基百科,斐波纳契数列
好了,题目来了:请用程序实现斐波纳契函数.
菜鸟的程序员想了想,画了个圈--不会.
一般的程序员想了想,撸起袖子,开工.
高手的程序员想了又想,慎重的写下了:
前者使用的是递归,后者使用的是简单的循环.《数据结构与问题求解(Java语言版)(第4版)》中指出:
永远不要用递归代替简单的循环.
当然二者的实现都是正确的,不过我们现在所要关注的问题是:效率
假设C(N)是在计算fib(n)时fib函数总共被调用的次数,而C(0)=C(1)=1,那么:
C(N)=C(N-1)+C(N-2)+1,其中1是调用fib(n)的次数.
对于N≧3,C(N)=F(N+2)+F(N-1)-1.(该公式是归纳法推导得出,具体推导方式本人也不会,有知道的可以告诉在下).
根据公式,当N=40时,F(40)=102334155,而总递归次数为F(42)+F(39)-1=331160281,超过了3亿.
递归调用会导致冗余计算.例如,计算f(n)时,需要计算,f(n-1)和f(n-2),而计算f(n-1)时需要计算f(n-2)和f(n-3),重复计算了f(n-2),而这种重复计算会随着n的增加爆炸性的增长.故而,不推荐使用递归解决斐波纳契函数.
另,看到一篇好文章,引用过来.斐波那契数列算法分析
在数学上,费波那西数列是以递归的方法来定义:
用文字来说,就是费波那西数列由 0 和 1 开始,之后的费波那西系数就由之前的两数相加。首几个费波那西系数是(OEIS A000045):
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,………………
特别指出:0不是第一项,而是第零项。
摘自维基百科,斐波纳契数列
好了,题目来了:请用程序实现斐波纳契函数.
菜鸟的程序员想了想,画了个圈--不会.
一般的程序员想了想,撸起袖子,开工.
public static int fib(int n){ if(n<=2){ return 1; }else{ return fib(n-1)+fib(n-2); } }
高手的程序员想了又想,慎重的写下了:
public static int fibonacci(int n) { if (n <= 2) { return 1; } int result = 0; int first = 0, second = 1; for (int i = 1; i < n; i++) { result = first + second; first = second; second = result; } return result; }
前者使用的是递归,后者使用的是简单的循环.《数据结构与问题求解(Java语言版)(第4版)》中指出:
永远不要用递归代替简单的循环.
当然二者的实现都是正确的,不过我们现在所要关注的问题是:效率
假设C(N)是在计算fib(n)时fib函数总共被调用的次数,而C(0)=C(1)=1,那么:
C(N)=C(N-1)+C(N-2)+1,其中1是调用fib(n)的次数.
对于N≧3,C(N)=F(N+2)+F(N-1)-1.(该公式是归纳法推导得出,具体推导方式本人也不会,有知道的可以告诉在下).
根据公式,当N=40时,F(40)=102334155,而总递归次数为F(42)+F(39)-1=331160281,超过了3亿.
递归调用会导致冗余计算.例如,计算f(n)时,需要计算,f(n-1)和f(n-2),而计算f(n-1)时需要计算f(n-2)和f(n-3),重复计算了f(n-2),而这种重复计算会随着n的增加爆炸性的增长.故而,不推荐使用递归解决斐波纳契函数.
另,看到一篇好文章,引用过来.斐波那契数列算法分析
相关文章推荐
- java使用递归,非递归方式实现二叉树的三种常见遍历方式
- 递归的使用——关于括号排列(分别使用Java和C++算法实现)
- ML的DOM解析 Java实现 使用递归解析一个XML文档
- java使用递归,非递归方式实现二叉树的三种常见遍历方式
- Java数据结构之递归与三角函数的运用,使用3种方法实现三角
- XML的DOM解析 Java实现 使用递归解析一个XML文档
- JAVA使用循环和递归方法实现斐波拉切数列
- java使用递归迭代实现流程图展示(仅供参考)
- java实现四则运算,难点主要在理解加减乘除优先级以及使用递归
- Java(二分查找算法实现,分别使用递归和非递归方式)
- java使用递归和非递归实现二分查找
- 使用递归删除树形结构的所有子节点(java和mysql实现)
- 使用java递归实现文件及文件夹的复制
- 使用递归求数组最大值(java实现)
- java 用递归实现:输入一个整数,用字符串逆序输出,例如输入123,输出321 ,不使用全局变量
- 简单说明什么是递归?什么情况会使用?并使用Java实现一个简单的递归程序。
- 使用java的File类遍历文件夹,打印树状结构(递归实现)
- Java使用分治递归的思想实现快速排序
- 二叉树遍历,已知前序遍历与中序遍历,求后续遍历 使用java(递归方式)实现
- 谨慎地使用递归之斐波那契递归实现的分析