javascript基础二十二:举例说明你对尾递归的理解,有哪些应用场景

一、递归
递归(英语:Recursion)
在数学与计算机科学中,是指在函数的定义中使用函数自身的方法
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数
其核心思想是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
一般来说,递归需要有边界条件、递归前进阶段和递归返回阶段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回
下面实现一个函数 pow(x, n),它可以计算 x 的 n 次方
使用迭代的方式,如下:
function pow(x, n) {let result = 1;// 再循环中,用 x 乘以 result n 次for (let i = 0; i < n; i++) {result *= x;}return result;
}
使用递归的方式,如下:
function pow(x, n) {if (n == 1) {return x;} else {return x * pow(x, n - 1);}
}
pow(x, n) 被调用时,执行分为两个分支:
if n==1 = x/
pow(x, n) =\else = x * pow(x, n - 1)
也就是说pow 递归地调用自身 直到 n == 1

为了计算 pow(2, 4),递归变体经过了下面几个步骤:
- pow(2, 4) = 2 * pow(2, 3)
- pow(2, 3) = 2 * pow(2, 2)
- pow(2, 2) = 2 * pow(2, 1)
- pow(2, 1) = 2
因此,递归将函数调用简化为一个更简单的函数调用,然后再将其简化为一个更简单的函数,以此类推,直到结果
二、尾递归
尾递归,即在函数尾位置调用自身(或是一个尾调用本身的其他函数等等)。尾递归也是递归的一种特殊情形。尾递归是一种特殊的尾调用,即在尾部直接调用自身的递归函数
尾递归在普通尾调用的基础上,多出了2个特征:
- 在尾部调用的是函数自身
- 可通过优化,使得计算仅占用常量栈空间
在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,递归次数过多容易造成栈溢出
这时候,我们就可以使用尾递归,即一个函数中所有递归形式的调用都出现在函数的末尾,对于尾递归来说,由于只存在一个调用记录,所以永远不会发生"栈溢出"错误
实现一下阶乘,如果用普通的递归,如下:
function factorial(n){if(n===1) return 1return n * factorial(n-1)
}
undefined
factorial(5)
120
如果n等于5,这个方法要执行5次,才返回最终的计算表达式,这样每次都要保存这个方法,就容易造成栈溢出,复杂度为O(n)
如果我们使用尾递归,则如下:
function factorial(n,total=1){if(n===1) return totalreturn factorial(n-1,n*total)
}
factorial(5) // 120
可以看到,每一次返回的就是一个新的函数,不带上一个函数的参数,也就不需要储存上一个函数了。尾递归只需要保存一个调用栈,复杂度 O(1)
二、应用场景
数组求和
function sum(arr, total) {if(arr.length === 1) {return total}return sum(arr, total + arr.pop())
}
使用尾递归优化求斐波那契数列
function factorial2 (n, start = 1, total = 1) {if(n <= 2){return total}return factorial2 (n -1, total, total + start)
}
数组扁平化
let a = [1,2,3, [1,2,3, [1,2,3]]]
// 变成
let a = [1,2,3,1,2,3,1,2,3]
// 具体实现
function flat(arr = [], result = []) {arr.forEach(v => {if(Array.isArray(v)) {result = result.concat(flat(v, []))}else {result.push(v)}})return result
}
数组对象格式化
let obj = {a: '1',b: {c: '2',D: {E: '3'}}
}
// 转化为如下:
let obj = {a: '1',b: {c: '2',d: {e: '3'}}
}// 代码实现
function keysLower(obj) {let reg = new RegExp("([A-Z]+)", "g");for (let key in obj) {if (obj.hasOwnProperty(key)) {let temp = obj[key];if (reg.test(key.toString())) {// 将修改后的属性名重新赋值给temp,并在对象obj内添加一个转换后的属性temp = obj[key.replace(reg, function (result) {return result.toLowerCase()})] = obj[key];// 将之前大写的键属性删除delete obj[key];}// 如果属性是对象或者数组,重新执行函数if (typeof temp === 'object' || Object.prototype.toString.call(temp) === '[object Array]') {keysLower(temp);}}}return obj;
};
相关文章:
javascript基础二十二:举例说明你对尾递归的理解,有哪些应用场景
一、递归 递归(英语:Recursion) 在数学与计算机科学中,是指在函数的定义中使用函数自身的方法 在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数 其核心思想是把一个大型…...
hive中如何计算字符串中表达式
比如 select 1(2-3)(-4.1-3.1)-(4-3)-(-3.34.3)-1 col ,1(2-3)(-4.1-3.1)-(4-3)-(-3.34.3)-1 result \ 现在的需求式 给你一个字符串如上述col 你要算出result。 前提式 只有和-的运算,而且只有嵌套一次 -(4-3)没有 -(-4(3-(31)))嵌套多次。 第一步我们需要将运…...
如何将maven项目改为springboot项目?
将 Maven 项目转换为 Spring Boot 项目需要进行以下步骤: 1. 在 Maven 项目中添加 Spring Boot 的依赖。可以通过在 pom.xml 文件中添加以下依赖来实现: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>…...
Java与查找算法(5):哈希查找
一、哈希查找 哈希查找,也称为散列查找,是一种基于哈希表的查找算法。哈希表是一种数据结构,它将键(key)映射到值(value),使得查找某个键对应的值的时间复杂度为O(1)。哈希查找的过…...
Vercel部署个人博客
vercel 部署静态资源网站极其方便简单,并且有可观的访问速度,最主要的是免费部署。 如果你还没有尝试的话,强烈建议去使用一下。 演示博客演示http://202271.xyz/?vercel vercel 介绍 注册账号 进入Vercel官网https://vercel.com&#x…...
【论文阅读】An Object SLAM Framework for Association, Mapping, and High-Level Tasks
一、系统概述 这篇文章是一个十分完整的物体级SLAM框架,偏重于建图及高层应用,在前端的部分使用了ORBSLAM作为基础框架,用于提供点云以及相机的位姿,需要注意的是,这篇文章使用的是相机,虽然用的是点云这个…...
《metasploit渗透测试魔鬼训练营》学习笔记第六章--客户端渗透
四.客户端攻击 客户端攻击与服务端攻击有个显著不同的标识,就是攻击者向用户主机发送的恶意数据不会直接导致用户系统中的服务进程溢出,而是需要结合一些社会工程学技巧,诱使客户端用户去访问这些恶意数据,间接发生攻击。 4.1客户…...
华为OD机试真题 Java 实现【Linux 发行版的数量】【2023Q1 100分】
一、题目描述 Linux 操作系统有多个发行版,distrowatch.com 提供了各个发行版的资料。这些发行版互相存在关联,例如 Ubuntu 基于 Debian 只开发而 Mint 又基于 Ubuntu 开发,那么我们认为 Mint 同 Debian 也存在关联。 发行版集是一个或多个相关存在关联的操作系统发行版,…...
VMware ESXi 8.0U1a macOS Unlocker OEM BIOS (标准版和厂商定制版)
VMware ESXi 8.0 Update 1a macOS Unlocker & OEM BIOS (标准版和厂商定制版) ESXi 8.0U1 标准版,Dell HPE 联想 浪潮 定制版 请访问原文链接: https://sysin.org/blog/vmware-esxi-8-u1-oem/,查看最新版。原创作品,转载请保…...
Effective STL_读书笔记
Effective STL 1. 容器条例01:慎重选择容器类型条例02:不要试图编写独立于容器类型的代码条例03:确保容器中对象的拷贝正确而高效条例04:调用empty而不是检查size()是否为空条例05:区间成员函数优先于与之对应的单元素…...
通过yum:mysql5.6-msyql5.7-mysql8.0升级之路
一 前言 mysql的yum源 https://dev.mysql.com/downloads/repo/yum/ https://dev.mysql.com/get/mysq57-community-release-el7-7.noarch.rpm服务器信息 2c2g40GB [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [rootlocalhost ~]# una…...
C语言数据存储 — 整型篇
C语言数据存储 — 整型篇 前言1. 数据类型介绍1.1 类型的基本分类 2. 整型在内存中的存储2.1 原码、反码、补码2.1.1 为什么数据存放在内存中存放的是补码 2.2 大小端介绍2.2.1 什么是大小端?2.2.2 为什么有大端和小端?2.2.3 一道百度系统工程师笔试题 3…...
高级Excel功能教程_编程入门自学教程_菜鸟教程-免费教程分享
教程简介 Excel是办公室自动化中非常重要的一款软件,Excel函数则是Excel中的内置函数。Excel函数共包含11类,分别是数据库函数、日期与时间函数、工程函数、财务函数、信息函数、逻辑函数、查询和引用函数、数学和三角函数、统计函数、文本函数以及用户…...
ChatGPT会取代低代码开发平台吗?
编程作为一种高端技能,向来是高收入高科技的代名词。近期,伴随着ChatGPT在全球的爆火,过去通过窗口“拖拉拽”的所见即所得方式的低代码开发模式,在更加智能和更低成本的AI搅局之下,又面临了更深层次的影响。 低代码平…...
Linux :: 文件内容操作【5】:echo 指令 与 输入重定向、输出重定向、追加重定向在文件内容写入中的简单用法!
前言:本篇是 Linux 基本操作篇章的内容! 笔者使用的环境是基于腾讯云服务器:CentOS 7.6 64bit。 学习集: C 入门到入土!!!学习合集Linux 从命令到网络再到内核!学习合集 说明&#x…...
【RocketMQ】重试机制及死信消息处理
【RocketMQ】重试机制及死信消息处理 文章目录 【RocketMQ】重试机制及死信消息处理1. 重试机制1.1 生产者重试1.2 消费者重试1.2.1 死信队列 参考文档: 官方文档 1. 重试机制 1.1 生产者重试 rocketmq生产者发送消息失败默认重试2次(同步发送为2次,异…...
Mysql DDL执行方式-pt-osc介绍 | 京东云技术团队
1 引言 大家好,接着上次和大家一起学习了《MySQL DDL执行方式-Online DDL介绍》,那么今天接着和大家一起学习另一种MySQL DDL执行方式之pt-soc。 在MySQL使用过程中,根据业务的需求对表结构进行变更是个普遍的运维操作,这些称为…...
C++ stack容器介绍
🤔stack容器介绍: 📖 stack是一种数据结构,也可以被称为堆栈。它是一个容器,只允许在最顶层进行插入和删除,并且只能访问最后一个插入的元素。这个元素称为栈顶。所有新插入的元素都被放置在栈顶上面&#…...
在 Git 中撤消更改的 6 种方法!
目录 1. 修改最近的提交 2. 将分支重置为较旧的提交 硬重置 软重置分支 创建备份分支 3. 交互式变基 删除旧提交 改写提交消息 编辑旧提交 压缩 4. 还原提交 5. 签出文件 6. 使用 Git Reflog 当使用 Git 进行项目代码管理时,难免会出现一些错误操作或需…...
LiveGBS国标GB/T28181国标平台功能-电子地图移动位置订阅mobileposition地图定位GPS轨迹坐标位置获取redis获取位置
LiveGBS国标GB/T28181国标平台功能-电子地图移动位置订阅mobileposition地图定位GPS轨迹坐标位置获取redis获取位置 1、位置订阅1.1、国标设备编辑1.2、选择设备开启位置订阅1.3、全局开启位置订阅1.4、通过目录订阅获取位置(少数情况) 2、经纬度信息查询2.1、访问接口获取2.1.…...
Saleor:应对现代电商架构挑战的无头商业引擎解决方案
Saleor:应对现代电商架构挑战的无头商业引擎解决方案 【免费下载链接】saleor Saleor Core: the high performance, composable, headless commerce API. 项目地址: https://gitcode.com/gh_mirrors/sa/saleor 在数字化转型浪潮中,电商平台面临的…...
Web性能优化:Core Web Vitals实战
Web性能优化:Core Web Vitals实战 大家好,我是欧阳瑞(Rich Own)。今天想和大家聊聊Web性能优化这个重要话题。作为一个全栈开发者,页面性能直接影响用户体验和业务转化。今天就来分享一下Core Web Vitals的优化经验。 …...
震惊!数十万家企业用软件监控员工,数据竟流向广告平台和经纪商!
官宣惊人内幕数十万家企业使用软件监控员工,新研究发现,许多职场监控工具不仅与雇主共享数据,还与数字广告平台和数据经纪商共享。研究详情这项研究由哥伦比亚法学院法律与经济中心高级研究员、前联邦贸易委员会首席技术专家斯蒂芬妮阮&#…...
程序员35岁以后最好的投资:不是买房,是这3样东西
当“35岁红线”撞上测试人的职业围城如果你在某个深夜刷到“程序员35岁以后该何去何从”的帖子时,心底划过一丝隐痛,那你绝不是一个人。而对于软件测试从业者而言,这种焦虑往往被放大得更加具体——当“点点点”的手工测试逐渐被自动化替代&a…...
贡献指南 | 参与 Harmonybrew 开源社区共建规范
贡献指南 | 参与 Harmonybrew 开源社区共建规范 欢迎大家加入鸿蒙PC社区 Harmonybrew 是面向 OpenHarmony/鸿蒙系统的 Homebrew 移植开源项目,依托多仓库协作模式,实现包管理器适配、软件包移植、工具适配、文档维护等全链路能力。为规范社区贡献流程、…...
无需复杂代理快速为你的项目接入GPT4与Claude等多模型
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 无需复杂代理快速为你的项目接入GPT4与Claude等多模型 基础教程类,面向希望在一个项目中灵活调用不同厂商大模型的开发…...
首次购买Token Plan套餐,在真实项目中的成本控制效果初探
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 首次购买Token Plan套餐,在真实项目中的成本控制效果初探 1. 项目背景与成本考量 作为一名独立开发者,我最…...
IT运维、远程协助必看!ToDesk录屏功能实测:被控方也能“回放”操作全程
Hello大家,不知道各位有没有注意到,在ToDesk远程控制上新的V4.8.8.9版本中,无论是在基本设置还是在远控连接过程中的悬浮球功能栏里都能看见【录屏设置/开始录屏】这一项!那么,这究竟是何意味呐?又有哪些人…...
构造函数、this指向和原型链机制
今天在刷力扣 [146. LRU 缓存](https://leetcode.cn/problems/lru-cache/) 的时候,遇到了原型链的写法,想想这个写法我正式开发中从来都没有用过,到底是个什么玩意?遂将各个节点和变量都定义在外面,但是代码居然报错啦…...
WeChatFerry微信机器人完整指南:构建企业级智能自动化助手
WeChatFerry微信机器人完整指南:构建企业级智能自动化助手 【免费下载链接】WeChatFerry 微信机器人,可接入DeepSeek、Gemini、ChatGPT、ChatGLM、讯飞星火、Tigerbot等大模型。微信 hook WeChat Robot Hook. 项目地址: https://gitcode.com/GitHub_Tr…...
