关于JavaScript递归经典案例题详析
作者:奥特曼 发布时间:2024-07-19 16:31:10
什么是递归,它是如何工作的?
我们先来看一下递归(recursion)的定义:
递归是一种解决问题的有效方法,在递归过程中,函数将自身作为子例程调用。
简单说程序调用自身的编程技巧叫递归。递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止。
使用递归需要避免出现死循环,为了确保递归正确工作,递归程序应该包含2个属性:
基本情况(bottom cases),基本情况用于保证程序调用及时返回,不在继续递归,保证了程序可终止。
递推关系(recurrentce relation),可将所有其他情况拆分到基本案例。
函数中自己调用自己就是递归,切记要有终止条件,不然进入死循环
一、求和
(1)数字求和
function sum(n){
if(n===1){
return n=1
}
return n+sum(n-1)
}
console.log(sum(5));
执行顺序
5+sum(n-1)
5+4+sum(n-1)
5+4+3+sum(n-1)
5+4+3+2sum(n-1)
5+4+3+2+1
(2)数组求和
function sum(arr) {
var len = arr.length
if (len == 0) {
return 0
} else if (len == 1) {
return arr[0]
} else {
return arr[0] + sum(arr.slice(1))
}
}
let arr = [ 1, 2, 3, 4, 5 ]
console.log(sum(arr))
执行顺序
1+sum(2,3,4,5)
1+2+sum(3,4,5)
1+2+3(4,5)
1+2+3+4+sum(5)
1+2+3+4+5
1+2+3+9
1+2+12
1+14
15
二、数据转树
let data = [{
id: "01",
pid: "",
"name": "老王"
},
{
id: "02",
pid: "01",
"name": "小张"
}
]
function fn(data, rootId = '') {
const children = [] //定义一个空数组
data.forEach(item => {
if (item.pid === rootId) { //如果每一项的pid=rootId就添加到数组里
children.push(item)
item.children = fn(data, item.id)
}
});
return children
}
使用递归转树 要知道根的pid是什么值才能进行下一步操作,作为起点。
执行顺序
三、汉诺塔
规则 下面三个柱子分别设为 a 、b、 c、 目标把a中的所有盘子分别从大到小依次放到c柱子中,每次只能移动一个盘子
实现思路:
将n-1个盘子从a挪到b
将n盘子从a挪到c
将n-1个盘子从b挪到c
function fn(num, start, middle, end) {
if(num>0){
fn(num-1,start,end,middle)
console.log(start+'====>'+end);
fn(num-1,middle,start,end)
}
}
fn(2,'a','b','c')
把 num作为盘子的数量 start 作为a盘子 middle作为b盘子 end作为c盘子
例如 2个盘子的执行顺序
1.第一行 把2带进去 num>0 执行第一个函数fn(2-1,start,end,middle) 又去执行了fn(1-1,start,end,middle) 发现num不大于0不仅如此if条件,回过来看 fn(2-1,start,end,middle) ,输出 console.log(a===>b)
2.第二行console.log(start+'====>'+end); 直接输出 a===>c
3.第三行 fn(2-1,middle,start,end) 执行 console.log(b===>c) 下次再去执行 fn(1-1,middle,start,end) 进入不了循环执行完毕
执行顺序有点抽象,实在不理解就按照最简单的思路去做 fn(num, start, middle, end) ,平常我们玩游戏怎么玩就去怎么做,初始图
fn(num-1,start,middle,end) 把 第二个的参数位置作为要移动的盘子 把第四个的参数位置作为移动目标 每次看图把这个公式带进去
第一步 fn(num-1,start,end,middle) 例如两个盘子 肯定是先把a-1放到b上
第二步 把盘子a放c上直接输出 console.log('a===>c')
第三步 把盘子b放c上 fn(num-1,middle,start,end,)
四、斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、
function Fibonacci(n) {
return n <= 1?1:Fibonacci(n - 1) + Fibonacci(n - 2)
}
除了前两个 每次都是前一个数和前两个数的和相加等于第三个数
例如数字5举例 前一项是3 前两项是2 3+2=5
来源:https://blog.csdn.net/m0_46846526/article/details/118417014


猜你喜欢
- json 作为一种通用的编解码协议,可阅读性上比 thrift,protobuf 等协议要好一些,同时编码的 size 也会比 xml 这类
- 前言大家在做数据抓取的时候,经常遇到由于网络问题导致的程序保存,先前只是记录了错误内容,并对错误内容进行后期处理。原先的流程:def cra
- 这里不跟大家再去把Vue文档上的一些指令用法或者基础知识再复述一遍,既然是从入门到实战,我直接将平时项目中需要实现的一些效果拆分成模块。你们
- 1.如何在网页中插入空格 我们在用Dreamweaver的所见即所得编辑模式下编辑中文网页时,往往需要
- 阅读上一章:Chapter 6 短语元素Chapter 7 锚点HTML中的链接,正确的说法应该称作"锚点",它不仅让我
- 本文代码是使用python抓取京东小米8手机的配置信息首先找到小米8商品的链接:https://item.jd.com/7437788.ht
- 半年前第一次做脚本编码的时候,由于没有什么使用经验,于是在51js上询问了一下encode脚本和normal脚本混用是否有什么问题呢?结果没
- 一、互联网人的焦虑互联网人是最焦虑的那批人,也是最爱学习的那批人。没办法,互联网行业的节奏实在太快了,每天都生活在信息 * 的环境里,“风口”
- 最近几天了解了一下人脸识别,应用场景可以是图片标注,商品图和广告图中有没有模特,有几个模特,模特的性别,年龄,颜值,表情等数据的挖掘。基础的
- 调取摄像头的实现import numpy as npimport cv2cap = cv2.VideoCapture(0)#参数为0时调用本
- 问题1:使用.net2005自带的SQL-Express连接不上。解决方法:1.网络防火墙阻止数据库连接;2.默认SQL-Express没有
- 阿里云提供了基于命名空间的 V2 版 SDK,但是文档不是很完整,使用门槛比较高,于是我封装了一个 Composer 包:https://g
- 下面的这个函数实现的功能是列出某文件夹下的所有文件,以文件名字母排序,先数字后字母再到中文。<%
- 一、贝叶斯分类介绍贝叶斯分类器是一个统计分类器。它们能够预测类别所属的概率,如:一个数据对象属于某个类别的概率。贝叶斯分类器是基于贝叶斯定理
- 本文实例讲述了JS实现淡入淡出图片效果的方法。分享给大家供大家参考,具体如下:效果:鼠标移入时,图片由半透明逐渐变成清晰,移出时,由清晰变为
- 农历新年将至,支付宝红包打了一仗,微信在朋友圈屏蔽了它的分享,但单防守还不行,进攻才是最好的防守。昨日,微信支付现金红包接口正式开放,只需开
- 今天将webserice里面的一个代码,拷到一个C#类,结果运行编译错误。DataBase = Server.MapPath("d
- mock简介mock原是python的第三方库python3以后mock模块已经整合到了unittest测试框架中,不用再单独安装Mock这
- 本文记录了windows下python的安装,供大家参考,具体内容如下—–因为我是个真小白,网上的大多入门教程并不适合我这种超级超级小白,有
- fit_generator 是 keras 提供的用来进行批次训练的函数,使用方法如下:model.fit_generator(genera