什么是递归?

程序调用自身的编程技巧称为递归( 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. java 图片上传

    代码是最有力量的,嘎嘎 @CrossOrigin@ApiOperation(value = "上传图片", notes = "上传图片", httpMethod ...

  2. 格雷码(Grey Code)生成规则

    (1) Grey码在FPGA实际应用中是实用的码,在8421BCD码累加计数器中,如果寄存器需要发生多位(两位或者以上)的跳变,会出现中间态,这样作为组合逻辑的输入是不稳妥的. 下面看两个中间态的例子 ...

  3. Netty 异步模型

    简介 Netty中的 I/O 操作是异步的, 包括 Bind.Write.Connect 等操作会简单的返回一个ChannelFuture. 调用者不能立刻获得结果, 而是通过Future-Liste ...

  4. Oracle 建库

    Oracle得安装就不多说了 不过还是建议直接去官网下  其他渠道可能会导致安装问题  具体自己慢慢体会吧  !  下面主要说下怎么用Oracle建库并且建用户角色 Database configur ...

  5. 记号一下用iptables做的端口转发

    iptables -t nat -I PREROUTING -p tcp -m tcp --dport 83 -j DNAT --to-destination 192.168.1.55:443ipta ...

  6. 小技巧:使用命令行打开vscode 以及 sublime 工具

    vscode手动打开vscode command + shift + p 打开命令面板(或者点击菜单栏 查看>命令面板)输入 shell 选择 install code command in P ...

  7. android 动画基础绘——view 动画(二)[补]

    前言 这个是对view 动画的补充,是一些view 动画的特殊使用场景. 回顾第一篇关于view 动画的,我介绍到view的动画都是针对元素本身的. 当我们开发view动画的时候,我们看到几个元素在做 ...

  8. ELK 安装Beat

    章节 ELK 介绍 ELK 安装Elasticsearch ELK 安装Kibana ELK 安装Beat ELK 安装Logstash Beat是数据采集工具,安装在服务器上,将采集到的数据发送给E ...

  9. webpack随笔2--编译ES6/ES7

    一.Babel 1.安装babel Bable-loader: babeljs.io babel最新版:npm install babel-loader@8.0.0-beta.0 @babel/cor ...

  10. 【Android】家庭记账本手机版开发报告六

    一.说在前面  昨天 1.创建登入和注册界面:2.向数据库添加一张用户表  今天 用图标显示账单情况 问题 1.使用第三方库 hellochart,时添加依赖构建失败 2.在 chertFragmen ...