参考链接:
javascript递归的实际应用场景https://blog.csdn.net/creabine/article/details/79027419
汉诺塔-递归算法(JS递归函数)https://blog.csdn.net/xiaoxiao520c/article/details/77620583
几个经典递归问题用js实现https://blog.csdn.net/qianqianstd/article/details/75807462
JavaScript实现递归算法的方法介绍https://www.php.cn/js-tutorial-416474.html
概念
递归算法,是将问题转化为规模缩小的同类问题的子问题,每一个子问题都用一个同样的算法去解决。一般来说,一个递归算法就是函数调用自身去解决它的子问题。
递归算法的特点:
- 在函数过程中调用自身。
- 在递归过程中,必须有一个明确的条件判断递归的结束,既递归出口。
- 递归算法简洁但效率低,通常不作为推荐算法。
function factorial (n) {
if(n === 1){
return 1;
}
return n * factorial(n-1);
}
factorial(5)
尾递归:
如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个函数是尾递归。当递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。
但是像上边那样递归会保存很多个调用帧,比如上边的factorial(5)
,这个方法要执行5次,才能返回最终的计算表达式,这样每次都要保存这个方法,就容易造成栈溢出。为了解决这个问题,我们会使用尾递归:
function factorial(n,total=1){
if(n===1){
return total;
}
return factorial(n-1,n*total);
}
factorial(5);
这样,每一次返回的就是一个新的函数,不带上一个函数的参数,也就不需要储存上一个函数了。只需要一个帧即可。
经典递归问题:
Q1——阶乘
问题描述: n! = n*(n-1)*...2*1
代码实现:
var factorial = functio