实现斐波那契数列的三种方式

首先说说斐波那契数列:
从文字上说,斐波那契数列由0和1开始,之后的斐波那契系数就由之前的两数相加,数列形式如下:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,………………
在数学上,是以递归的方法来定义:
F(0)=0
F(1)=1
F(n)= F(n-1)+ F(n-2)

实现需求:输入序号n返回得到对应斐波那契数
程序实现1——函数迭代

public int fnType1(int n)throws Exception{
  if(n==0){
   return 0;
  }else if(n==1||n==2){
   return 1;
  }else if(n>2){
   int temp=fnType1(n-1)+fnType1(n-2);
   if(temp<0){
    throw new Exception("Invalid value for int type, too large");
   }else{
    return temp;
   }
  }else{
   throw new Exception("IllegalArgument value for n,please enter n>=0 ");
  }
 } 

此种方式缺点:大量迭代不断消耗栈空间(搞web开发调试维护的都应该知道服务器栈资源的可贵,如果大量并发调用迭代导致服务器栈资源迟迟得不到回收,而导致web服务器崩溃),效率底,函数自闭性比较弱(优秀的接口应该对输入输出可能出现的错误信息进行捕捉,并提供清楚明了的处理结果),很容易出现错误,调试困难,实际应用中一般不建议使用这种方式,使用时迭代次数也不能超过3次;
程序实现2——时间换空间

public int fnType2(int n) {
        int result = -1;
        int temp1 = 0;
        int temp2 = 1;
        for (int index = 0; index <= n; index++) {
            if (index == 0) {
                result = temp1;
            } else if (index == 1) {
                result = temp2;
            } else {
                result = temp1 + temp2;
                if (result < 0) {
                    result = -2;
                    break;
                }
                temp1 = temp2;
                temp2 = result;
            }
        }
        return result;
    }

此方法主要使用于:使用场景一:对于对象或变量使用次数比较少,使用一次以后就不会再使用的场景;使用场景二:对于内存资源比较稀缺的实时性要求不是太高的嵌入式系统设计中多会采用此种方式;
程序实现3——空间换取时间

private static List<Integer> fnData = new ArrayList<Integer>();
    private static final int maxSize = 50000;

    private static void setFnData() {
        int result = -1;
        int temp1 = 0;
        int temp2 = 1;
        for (int index = 0; index <= maxSize; index++) {
            if (index == 0) {
                result = temp1;
            } else if (index == 1) {
                result = temp2;
            } else {
                result = temp1 + temp2;
                if (result < 0) {
                    result = -2;
                    break;
                }
                temp1 = temp2;
                temp2 = result;
            }
            fnData.add(result);
        }
    }

    public int getFnData(int n) {
        if (fnData.size() == 0) {
            setFnData();
        }
        if (fnData.size() > n && n >= 0) {
            return fnData.get(n);
        } else {
            return -1;
        }
    }

此方法一般用于:对象或变量在程序运行的整个生命周期都存在或频繁调用的场景,如调用外部WebService接口、抽象持续化层、常用配置文件参数加载等等

对于算法设计,不要盲目遵循概念,概念是死的,人是活的,只用结合具体的应用场景才能设计出优秀的算法和结构。

原文地址:https://www.cnblogs.com/DarrenChan/p/5721683.html