zoukankan      html  css  js  c++  java
  • 斐波纳契函数java实现的误区谨慎使用递归

    最近在研究算法,遇到了斐波纳契函数,即1,2,3,5,8,13,21,34,55,89,...,通用式为:f(n)=f(n-1)+f(n-2).

    在数学上,费波那西数列是以递归的方法来定义:

     F_0=0

    F_1=1

    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不是第一项,而是第零项。

    摘自维基百科,斐波纳契数列

    好了,题目来了:请用程序实现斐波纳契函数.

    菜鸟的程序员想了想,画了个圈--不会.

    一般的程序员想了想,撸起袖子,开工.

    1     public static int fib(int n){
    2         if(n<=2){
    3             return 1;
    4         }else{
    5             return fib(n-1)+fib(n-2);
    6         }
    7     }

    高手的程序员想了又想,慎重的写下了:

     1     public static int fibonacci(int n) {
     2 
     3         if (n <= 2) {
     4             return 1;
     5         }
     6 
     7         int result = 0;
     8         int first = 0, second = 1;
     9 
    10         for (int i = 1; i < n; i++) {
    11             result = first + second;
    12             first = second;
    13             second = result;
    14         }
    15 
    16         return result;
    17     }

    前者使用的是递归,后者使用的是简单的循环.《数据结构与问题求解(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的增加爆炸性的增长.故而,不推荐使用递归解决斐波纳契函数.

    另,看到一篇好文章,引用过来.斐波那契数列算法分析

  • 相关阅读:
    UVA 1025 A Spy in the Metro DP水题
    ZOJ 3814 Sawtooth Puzzle BFS
    ZOJ 3816 Generalized Palindromic Number
    UVA 10859 Placing Lampposts 树形DP
    UVA 11825 Hackers' Crackdown 状压DP
    POJ 2887 Big String 线段树 离线处理
    POJ 1635 Subway tree systems Hash法判断有根树是否同构
    BZOJ 3110 k大数查询 & 树套树
    sdoi 2009 & 状态压缩
    来自于2016.2.24的flag
  • 原文地址:https://www.cnblogs.com/geyifan/p/2920070.html
Copyright © 2011-2022 走看看