要理解递归就要先理解递归:手把手教你写递归

问:何为递归函数?
说人话:本身调用本身的函数就叫递归函数java

递归函数写法

实现一个递归函数,我将其归纳为是一个“推卸责任”的过程,分为3个步骤:算法

  1. 列出方法签名:明确该函数/方法的输入输出,由此写出它的方法签名(method’s signature),方法签名包括修饰符,返回值类型,方法名和参数列表。
  2. 完成边界状况(base case,也称基准状况):即找到“替罪羊”,由于不停地把问题往下级推卸,最后总得有人出来背锅。
  3. 完成递归状况(recursive case):即完成责任推卸链,把问题从第\(n\)层推卸到第\(n - 1\)层。

咱们将用求阶乘的例子来详细解释这3个步骤。数组

列出方法签名

首先,明确输入输出:咱们但愿只要给该方法/函数一个整数,就能返回它的阶乘。那么该递归方法的方法签名即为以下:数据结构

public int factorial(int n){};

这样咱们就完成了实现递归函数的第1个步骤了。函数

完成边界状况

很显然阶乘的边界状况就是求1的阶乘,它没有理由再把计算的责任推卸给任何人了,由于它本身就能直接得出计算结果1,因此求1的阶乘就是咱们要找的那只“替罪羊”。spa

所以,基准状况即为以下:code

if (n == 1) return n;

完成递归状况

提早找好了“替罪羊”,接下来咱们只须要把“责任推卸链”完成,让责任一级一级最终推卸到替罪羊身上,就能够大功告成!递归

而要完成这条“责任推卸链”,其实就是列出关于原问题和子问题的数学等价关系式ci

对于求阶乘而言,原问题和子问题的等价关系式为:\(n! = n \times (n - 1)!\)。这样,就将问题从第\(n\)层成功地转移到了第\(n-1\)层。get

那么对应的代码实现即为以下:

else return n * factorial(n - 1);

综合以上3个步骤,完整版的实现阶乘的递归函数即为:

/** Returns n factorial. */
public int factorial(int n) {
    // Base case
    if (n == 1)
        return n;

    // Recursive case 
    else 
        return n * factorial(n - 1);
}

在这个递归函数里,咱们定义了递归状况来一步步简化问题,也定义边界状况来计算出最终的边界值。因此咱们大可放心地调用该函数,让它自行去解决问题。

看到这里,相信你已经掌握了递归函数的写法。能够看出,写出一个递归函数并无那么容易。而咱们可不但愿当咱们绞尽脑汁憋出一个递归函数后,却换来老板一句“画蛇添足,净瞎折腾”。

那要避免这种状况,咱们得先弄清楚一个前提:何时派上递归最为合适?

何时应用递归

咱们先来谈谈递归的缺点:

  1. 对空间消耗大,容易致使栈溢出
    递归是调用自身的函数,而函数的每次调用都会在栈中产生调用帧(call frame, 用来保存内部变量、返回点等信息),可栈的空间是有限的,无法一次同时保存过多的调用帧。因此若是调用的次数多了就容易致使栈溢出,对空间消耗大。
  2. 对时间消耗大,致使运行效率低
    首先,往栈中压入和弹出数据须要时间;此外,递归中常常会产生不少重复计算,例如在斐波那契数列的递归实现中,当n = 5时,须要计算一遍的fibonacci(3),推导到n = 4时,又须要计算一遍fibonacci(3)。也就是说求一个5的阶乘须要计算两遍的fibonacci(3),因此说时间效率低。
    (能够利用一个数组或哈希map来保存已计算出的结果来避免重复计算)

而递归主要是用于如下两种状况:

  1. 数据结构自己就是按递归的形式定义的。
    例如斐波那契数列、n的阶乘、二叉树的遍历、图的搜索等。这种状况下,以其人之道还治其人之身固然是很直观了当的作法。
  2. 问题能以一样的解法逐级减少问题规模
    例如分治算法、回溯算法等,它们能用一样的解法去一步步减少问题规模,因此用递归实现起来就很方便。

因此,除非是以上两种状况,不然尽可能避免使用递归,以免对空间和时间产生大的消耗。(P.S. 把浪费的这些功夫拿去打王者荣耀它不香吗...)

总结

递归函数是本身调用本身的函数。经过列出方法签名,完成基准状况和递归状况便可完成一个递归函数。可是用递归实现一般会对时间和空间产生大的消耗,所以除非数据结构自己就是按递归的形式定义或是问题能以一样的解法逐级减少问题规模,不然应尽可能避免使用递归。

参考

  1. https://mp.weixin.qq.com/s/tqGKHZzSyDBgEp-oWsOztQ

创做不易,点个赞再走叭~

相关文章
相关标签/搜索