什么是递归?

程序调用自身的编程技巧称为递归( recursion)。递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量 。

递归的能力在于用有限的语句来定义对象的无限集合

一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

求和1···100

     function getSum(num) {
if(num === 1) {
return num
} else {
// return num + getSum(num - 1) // 如果 var getterSum = getSum, getSum = null 会报错
return num + arguments.callee(num - 1)
}
}
const value = getSum(1000) console.log(value)

奇数项 求和

// 第0项为1,第1项为3···
function foo(n){
if(n == 0) return 1;
return foo(n-1) + 2;
} function sum(n){
if(n == 0) return 1;
return foo(n) + sum(n-1);
} console.log(sum(1)) //

偶数项 求和

// 第0项为2,第1项为4···
function fn(n){
if(n == 0) return 2;
return fn(n-1) + 2;
}
function sum(n){
if(n==0) return 2;
return fn(n) + sum(n-1);
}
console.log(sum(1)) //

尾递归

函数在尾部调用自身就成为尾递归。

        function factorial(n) {
if(n === 1) return n
return n * factorial(n - 1)
}
// 计算n的阶乘,最多需要保存n个调用记录,复杂度为O(n)
console.time(1)
console.log(factorial(5)) //
console.timeEnd(1) // 1: 1.60400390625ms // 如果改为尾递归,只需要保留一个调用记录,复杂度为O(1)
function factorial01(n, tntal) {
if(n === 1) return tntal
return factorial(n - 1, n * tntal)
}
console.time(2)
console.log(factorial01(5, 1)) //
console.timeEnd(2) // 2: 0.14404296875ms

Fibonacci(斐波那契)数列

        function Fibonacci(n) {
if(n <= 1) return 1
return Fibonacci(n - 1) + Fibonacci(n - 2)
} console.time(1)
console.log(Fibonacci(20)) //
console.timeEnd(1) // 1: 4.115966796875ms // console.time(2)
// console.log(Fibonacci(100)) // 10946
// console.timeEnd(2) // stack overflow 堆栈溢出

Fibonacci(斐波那契)数列改写

通过一个正常形式的阶乘函数factorial,调用尾递归函数tailFactorial。

        // 尾递归优化
function Fibonacci01(n, ac1 = 1, ac2 = 1) {
if(n <= 1) return ac2
return Fibonacci01(n - 1, ac2, ac1 + ac2)
} console.time(3)
console.log(Fibonacci01(100)) //
console.timeEnd(3) // 3: 0.52197265625ms

柯里化(currying)

通过柯里化,将尾递归函数tailFactorial变为只接受一个参数的factorial。

ES5:

        function currying(fn, n) {
return function (m) {
return fn.call(this, m, n);
};
} function tailFactorial(n, total) {
if (n === 1) return total;
return tailFactorial(n - 1, n * total);
} const factorial = currying(tailFactorial, 1); factorial(5) //

ES6:

        function factorial(n, total = 1) {
if (n === 1) return total;
return factorial(n - 1, n * total);
} factorial(5) // 120

JavaScript之递归的更多相关文章

  1. Javascript中递归造成的堆栈溢出及解决方案

    关于堆栈的溢出问题,在Javascript日常开发中很常见,Google了下,相关问题还是比较多的.本文旨在描述如何解决此类问题. 首先看一个实例(当然你可以使用更容易的方式实现,这里我们仅探讨递归) ...

  2. 每天一个JavaScript实例-递归实现反转数组字符串

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. JavaScript的递归之更多例子

    更多例子 第二个递归的例子是求两个自然数的最大公约数(有没有回到令人怀念的中学时代).下面的程序用的是经典的辗转相除法. //greatest common divisor //假定a.b都是正整数 ...

  4. 前端笔试题目总结——应用JavaScript函数递归打印数组到HTML页面上

    数组如下: var item=[{ name:'Tom', age:70, child:[{ name:'Jerry', age:50, child:[{ name:'William', age:20 ...

  5. JavaScript对象---递归遍历对象

    JavaScript 中的所有事物都是对象:字符串.数值.数组.函数... 此外,JavaScript 允许自定义对象. JavaScript 对象 JavaScript 提供多个内建对象,比如 St ...

  6. javascript memoization递归优化

    memoize优化递归 function createRec(callback, cache) { cache = cache || []; var rec = function(n) { (n in ...

  7. javascript 将递归转化为循环

    function tco(f) { var value; var active = false; var accumulated = []; return function accumulator() ...

  8. JavaScript 函数递归

    递归函数 递归函数是在一个函数通过名字调用自身的情况下构成的 项目中例如树状结构渲染,对象深复制,等很多方面都会使用到递归函数 function factorial(num){ if (num < ...

  9. JavaScript通过递归合并JSON

    通过递归合并JSON: function mergeJSON(o, n) { let oType = Object.prototype.toString.call(o); let nType = Ob ...

  10. JavaScript利用递归和循环实现阶乘

    [实现方法] 1.利用while循环来做,当然for循环也可以. 2.递归 [代码内容] 偷懒,直接用onkeyup事件来限制来页面的输入 循环代码: //第一种方法 while循环 oCount.o ...

随机推荐

  1. sourcetree的安装

    参考博文: SourceTree安装教程和GitLab配置详解 关于Atlassian无法注册的问题 SourceTree跳过Atlassian账号,免登陆,跳过初始设置 sourcetree跳过注册 ...

  2. maven详解之 pom.xml 解释

    <project>:pom.xml的根标签,一个maven项目用一对<peoject></project>标签包裹. <modelVersion>4.0 ...

  3. servlet3.0的文件上传代码配置怎么写

    之前学习过xml配置servlet3.0的文件上传,但是变成code方式一直不知道怎么弄,相比较起来apache的文件上传配置和xml倒是没什么太大区别. 直接上代码:无需依赖,只要一个方法就好了cu ...

  4. webservice调试(XML参数)

    <![CDATA[ <?xml version="1.0" encoding="UTF-8"?><MsgText> <use ...

  5. Makefile入门1

    Linux中的编译脚本Makefile的讲解设计 概念 编译控制脚本(.c.h----->bin) Makefile最终要的是清晰编译链接的整个过程 Makefile的优化设计 工作原理 mak ...

  6. win下的常用8个命令

    windows下常用的几个指令 一,ping 它是用来检查网络是否通畅或者网络连接速度的命令.作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的 ...

  7. --转载 详细介绍java中的数据结构

    http://developer.51cto.com/art/201107/273003.htm 也许你已经熟练使用了java.util包里面的各种数据结构,但是我还是要说一说java版数据结构与算法 ...

  8. 小米手机收到升级鸿蒙OS提示?官方回应

    虽然尚未得到官方确认,但华为“鸿蒙”OS已经成为网络热门话题,在机圈引发热议. 本周,互联网上出现了显示为MIUI 10手机被锁定,屏幕上出现“小米将于2020年9月15日全面停止服务,届时您所有设备 ...

  9. netty权威指南学习笔记三——TCP粘包/拆包之粘包现象

    TCP是个流协议,流没有一定界限.TCP底层不了解业务,他会根据TCP缓冲区的实际情况进行包划分,在业务上,一个业务完整的包,可能会被TCP底层拆分为多个包进行发送,也可能多个小包组合成一个大的数据包 ...

  10. 英语学习 - 进行时态的被动 ( be being done )

    be being done  例: The story book was being read by him .