zoukankan      html  css  js  c++  java
  • 数据机构与算法学习(八)- 递归

    递归需要满足三个条件

    1. 一个问题的解可以分解为几个子问题的解

    2. 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一致。

    3. 存在递归终止条件

    如何编写递归代码

    最关键的是写出递推公式,找到终止条件,剩下将递推公式转化为代码

    假如有n个台阶,每次可以跨1个台阶或者2个台阶,请问走这n个台阶有哦多少种走法?

    n个台阶的走法就等于先走1台阶后,n-1个台阶的走法加上先走2台阶后,n-2个台阶的走法,用公式表示:

    f(n) = f(n-1) + f(n-2)

    有了递推公式,然后在看终止条件。有1台阶有1种走法,有2个台阶的话,有2中走法。所以

    f(1) = 1
    f(2) = 2

    有了终止条件和递推公式,那么最后转换为代码

    int f(int n){
        if(n == 1) return 1;
        if(n == 2) retrun 2;
        return f(n-1) + f(n-2);
    }

    总结一下,写递归代码的关键就是找到如何将大问题分解为小问题的规律,并且基于此写出递推公式,然后在推敲出终止条件,最后将递推公式和终止条件翻译成代码。

    递归代码的常见问题

    1. 递归代码要警惕堆栈溢出, 函数调用会使用栈来保存临时变量,如果递归很深的话, 一直压栈会有栈溢出风险,一般程序中栈是有大小设置的。

    2. 递归代码要警惕重复计算,像刚才n个台阶的那个例子,假设n=5的话,在n=5时会计算f(4)和f(3),在n=4时会计算f(3)和f(2).这样就有了重复计算。

    递归代码改为非递归代码

    还用n个台阶的例子

    int f(int n){
        if (n ==1 ) return 1;
        if( n == 2) return 2;
    
        int ret = 0;
        int pre = 2;
        int prepre = 1;
        for(int i = 3; i <= n; ++i){
            ret = pre + prepre;
            prepre = pre;
            pre = ret;
        }
        return ret;
    }

    笼统的讲,所有的递归代码都可以改为非递归的迭代循环方式。因为递归本身就是借助栈来实现的,只不过我们使用的栈是系统或者虚拟机本身提供的,我们没有感知罢了。

  • 相关阅读:
    1063. Set Similarity
    A1047. Student List for Course
    A1039. Course List for Student
    最大公约数、素数、分数运算、超长整数计算总结
    A1024. Palindromic Number
    A1023. Have Fun with Numbers
    A1059. Prime Factors
    A1096. Consecutive Factors
    A1078. Hashing
    A1015. Reversible Primes
  • 原文地址:https://www.cnblogs.com/OneSky-Mi/p/14620132.html
Copyright © 2011-2022 走看看