zoukankan      html  css  js  c++  java
  • 算法

    递归和迭代算法深入分析             

    原文链接:https://blog.csdn.net/liujian20150808/article/details/49717427

     


     递归的定义:

    程序调用自身的编程技巧称为递归( recursion)。

    迭代的定义:

    迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。


     接下来我们从一道题来引入这两种算法的比较:

    题目描述: QAQ在一个楼梯上,QAQ现在位于第0阶,无聊的QAQ发现,以他腿的长度,每次可以上1阶,2阶,3阶,而这个台阶一共有N阶,那么QAQ走到第N阶共有多少种走法?
                                       TimeLimit: 1000ms  MemoryLimit:65536KB

    多组测试数据,每组数据一行,包含一个数字N。(1 <= N <= 30)
    对于每组数据:
    输出到达第N阶共有多少种走法?


     解题思路:可以从1开始列举,直到找出规律,原理是加法原理

    算法描述:如果用n表示台阶的级数,a n表示某人走到第n级台阶时,所有可能不同的走法,容易得到:
    ① 当 n=1时,显然只要1种跨法,即a 1=1.
    ② 当 n=2时,可以一步一级跨,也可以一步跨二级上楼,因此,共有2种不同的
    跨法,即a 2=2.
    ③ 当 n=3时,可以一步一级跨,也可以一步三级跨,还可以第一步跨一级,第二步跨二级或第一步跨二级,第二步跨一级上楼,因此,共有4种不同的跨法,即a 3=4.
    ④ 当 n=4时,分三种情况分别讨论跨法:
    如果第一步跨一级台阶,那么还剩下三级台阶,由③可知有a3 =4(种)跨法.
    如果第一步跨二级台阶,那么还剩下二级台阶,由②可知有a2 =2(种)跨法.
    如果第一步跨三级台阶,那么还剩下一级台阶,由①可知有a1 =1(种)跨法.
    根据加法原理,有a 4= a1 +a2 +a3 =1+2+4=7
    类推 ,有
    a5= a2 +a3+a4 =2+4+7=13
    a6= a3 +a4+a5 =4+7+13=24
    a7= a4 +a5+a6=7+13+24=44
    a8= a5 +a6 +a7 =13+24+44=81


    1.递归算法的源代码:

    int digui(int n)
    {
    if(n == 1) return 1;
    if(n == 2) return 2;
    if(n == 3) return 4;
    else return digui(n - 1) + digui(n - 2) + digui(n - 3);
    }

       


    显然,当n值到了34就超时了,这是为什么呢?
    下面我们来分析一下该递归程序的运行过程:
    当n = 1,2,3的时候,该递归函数都只需要调用1次。
    当n = 4的时候,return digui(1) + digui(2) + digui(3)   此时,该递归函数被调用了3次。
    当n = 5的时候,return digui(2) + digui(3) + digui(4)   此时,该递归函数被调用了1+1+3=5次。
    当n = 6的时候,return digui(3) + digui(4) + digui(5)   此时,该递归函数被调用了1+3+5=9次。
    以此类推,有
    n7 = n4 + n5 + n6 = 3 + 5 + 9 = 17
    n8 = n5 + n6 + n7 = 5 + 9 +17 = 31
    n9 = n6 + n7 + n8 = 9+ 17 + 31 = 57
    ......
    这样计算下去到n = 34 的时候,该递归函数累计被调用了235795681次,已经是达到了亿的级别,如果是放在实际工作中,是一件多么可怕的事情,因为使用递归算这种类型的题目,会重复计算很多次,比如说当n = 34的时候,n = 1的时候的取值就被重复计算了53798080-1 = 53798079(可通过递归调用计算次数),重复计算次数都超过了5000万,可想而知算法的效率是多么的低,因此我们可以换一种思路,尽量减少重复计算的次数而提高算法效率,从而引进迭代算法。


    2.迭代算法的源代码:

    a1 = 1;
    a2 = 2;
    a3 = 4;
    for(i = 4;i <= N;i++)
    {
    sum = a1 + a2 + a3;
    a1 = a2;
    a2 = a3;
    a3 = sum;
    }

     

    而迭代算法到n = 34的时候,耗费的时间也还是忽略不计的
    下面分析一下迭代算法的过程:
    当n = 1,2,3的时候,跳过for循环,而输出的sum为自身值。
    当n = 4的时候,此时for循环次数为1次,计算得sum = 1 + 1 + 1 = 3;
    当n = 5的时候,此时for循环次数为2次,第一次计算得sum = 3,然后a2的值赋给a1,a3的值赋给a2,sum的值赋给a3,此时新的a1 = 1,a2 = 1,a3 = 3,然后程序运行到调整部分进行第二次循环,计算得sum = 5,然后跳出for循环输出sum的值为5.
    以此类推当n = 6,n = 7......的过程与上述过程类似。
    迭代的主要思想就是不断地以旧值来替换新值,从而有效的减少重复计算的次数。
    像以上的迭代算法的源代码,当n = 34时,重复计算n = 1,n = 2......的次数均为0,迭代程序就是从n = 4一直计算到n = 34的过程中,一直用旧值替换新值。程序耗费的时间只有for循环耗费的时间。与N的大小有关,呈线性O(n)阶,而且是系数为1的线性阶,for循环的执行次数为n-4.
    综上所述,当处理小的循环问题或者是阶乘等问题时,递归算法是一种效率非常低的算法,在找得到更好的算法的情况下,最好不要使用递归算法。

  • 相关阅读:
    文件字符输入输出流
    ava.io.InputStream & java.io.FileInputStream
    java.io.OutputStream & java.io.FileOutputStream
    java.lang.String & java.lang.StringBuilder
    文件过滤器
    递归
    原生camera应用 保存设置界面参数方法
    android 获取调用camera service的进程
    linux 查找,替换 常用命令
    将一个项目修改记录提交另外一个项目-> patch获取提交记录,repo 提交代码
  • 原文地址:https://www.cnblogs.com/wangqiwen-jer/p/11872338.html
Copyright © 2011-2022 走看看