zoukankan      html  css  js  c++  java
  • 递归的使用,斐波那契数列实现及优化

    一 .基本含义:

      ​    递归是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象。即递归是一个过程:函数不断引用自身,直到引用的对象已知。

    二 .使用递归的四大法则 :

        1. 基准情形: 必须有某些基准情形,它无需递归即可解出。

        2. 不断推进: 对于需要递归求解的情形,每次递归调用都必须使得求解状况朝着基准情形推进。

        3. 设计法则: 假设所有的递归调用都能运行。

        4. 合成效益法则:在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性工作。 

    其中第四点在递归的效率中至为关键。这是为什么用递归实现斐波那契数列的常规方法时效率很低的原因,而在二叉树中表现相当优良的原因!

    三.关于斐波那契数列的递归实现及优化

    斐波那契数列 又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2),即从第三项开始每一项都等于前面两项的和。

    根据定义很容易用递归实现的方法,

    public static long fib(long n){

    n1++;//记录被调用的次数

        if(n<2){//基准情形,法则1

            return n;

        }

       return fib(n-1)+fib(n-2);  //通过调用自身,不断推进直到达到基准情形,法则2,3

    }

    通过观察上面的代码,我们发现一个问题,当给定一个数N时,需要先计算N-1 和N-2的情况,但是在计算N-1时同样要用计算N-2的情况,每个递归调用都触发另外两个递归调用,而这两个调用的任何一个又将调用另外连个递归调用,这样冗余计算的增量是非常快的,例如图:

    再计算 fib(5)时,需要先求fib(4)和fib(3),

    而求fib(4)时又要求fib(3)fib(2)以此类推这样就做了大量重复计算造成了不必要的浪费,如果我们能把fib(3),fib(2),fib(1)计算好的数据先存起来,下次需要计算时直接调用就可以省去大量的重复计算,因而有了下面的优化方式:

    public static long newFib(long a,long b ,long n){

    n2++;//记录被调用的次数

      if(n>=2){  

       return newFib(a+b,a,n-1);//将本次计算的结果和上次计算的结果作为参数传入下一次计算中,以减少重复计算。第四法则

     }

      return a;

     }

    测试:

    static  int n1;

    static  int n2;

    public static void main(String[] args)
        {
            /* int n = 10;//第几个斐波那契数列  
                int a = 1; //斐波那契数列的第一项  
                int b = 1;//第二项  
                long i = fib(n);//普通的递归  
                long j =newFib(a,b,n);//优化后的递归  
                System.out.println("第n个fibon数是--"+i);  
                System.out.println("次数--"+n1);  
                System.out.println("第n个fibon数是--"+j);  
                System.out.println("次数--"+n2); 

    }

    输出结果为:

    根据结果可以看出,当n=10时,未经优化的方法被调用了177次,而优化后的方法仅仅被调用了9次,大大的减少了重复的计算,符合了递归调用的第四法则。

  • 相关阅读:
    一张图带你了解数据分析的完整流程,建议收藏
    【Unnatural × Lemon × 武汉】如果病毒结束了,你最想干什么事
    两万字深度介绍分布式系统原理!【收藏版】
    ETL的基础知识,看完你就全明白了!
    Java最大不重复子串
    一文速懂利用python字典的引用传递实现循环套娃(嵌套)
    ETSI GS MEC 015,MEP 带宽管理 API
    laravel 5.5 ajax返回错误信息
    laravel 5.5 ajax返回错误信息
    从实践出发:微服务布道师告诉你Spring Cloud与Boot他如何选择
  • 原文地址:https://www.cnblogs.com/wdxg0103/p/8629198.html
Copyright © 2011-2022 走看看