尝试理解 javascript 中 for 循环内的递归

2023-11-21

我一直盯着这个问题的答案,甚至在每次迭代中写下变量之类的东西。我只是不明白这里的过程。当我输入控制台日志时,我看到 permute 在到达此行之前被调用 input.length - 1 次 input.splice(i, 0, ch);当我完全迷失时,很难表达这个问题,但我想有些好奇的是:每次调用 permute 时,它​​都是该函数的一个新实例,有自己的闭包,对吧?因此函数内的变量更改不会影响其他调用中的变量?该函数每次调用时都会返回 permArr 吗?我想这不一定会影响第一次调用的返回? (我的直觉告诉我,第一次返回发生时,函数将停止运行)。

感谢您的见解。

JavaScript 中的排列?

var permArr = [],
usedChars = [];

function permute(input) {
  var i, ch;
  for (i = 0; i < input.length; i++) {
    ch = input.splice(i, 1)[0];
    usedChars.push(ch);
    if (input.length == 0) {
        permArr.push(usedChars.slice());
    }
    permute(input);
    input.splice(i, 0, ch);
    usedChars.pop();
  }
  return permArr
};

我会尝试一下。

Overview

您从两个具有全局作用域的数组开始:permArray最终将保存所有排列数组,并且usedChars是一个工作数组,用于通过所有递归调用构建每个单独的排列数组。重要的是要注意这些是only在创建的每个函数的范围内可访问的两个变量。所有其他变量对于它们自己的函数调用都有局部作用域。

然后是递归函数,它接受一个数组作为输入,并返回一个数组的数组,其中包含输入数组的所有可能的排列。现在,在这个特定的函数中,递归调用位于循环内。这很有趣,因为终止条件实际上比基本递归函数更复杂——当您传入空值时,递归调用终止input数组和 for 循环会跳过下一个递归调用。

Summary

考虑一个四元素数组输入。在较高层次上,该函数将循环遍历该数组的四个元素,取出每个元素,并计算该较小的三个元素数组的排列。对于所有这三个元素排列,它将把拉出的原始元素附加到开头,并将这四个元素数组中的每一个添加到permArray.

但是,为了找到较小的三元素数组的排列,我们取出每个元素,计算该较小的两个元素数组的排列,将取出的元素添加到每个排列的开头,然后return这三个元素数组中的每一个都位于递归调用堆栈中,因此可以将原始的第四个元素添加到开头并计为排列。

但是,为了找到较小的两个元素数组的排列,我们取出每个元素,计算一个元素的较小数组的排列,将取出的元素添加到每个排列的开头,然后return这两个元素数组中的每一个都位于递归调用堆栈中,因此可以将原始的第三个元素添加到该排列的开头并返回堆栈。

但是,为了找到较小的一个元素数组的排列,我们取出该元素并计算该空数组的排列,该空数组刚刚返回,而我们又将我们的一个元素返回到堆栈中,因此原始的第二个元素元素可以添加到该排列的开头并返回堆栈。

Details

让我们记下该函数中的一些步骤:

var permArr = [],
usedChars = [];

function permute(input) {
  var i, ch;
  for (i = 0; i < input.length; i++) {     //   loop over all elements 
    ch = input.splice(i, 1)[0];            //1. pull out each element in turn
    usedChars.push(ch);                    //   push this element
    if (input.length == 0) {               //2. if input is empty, we pushed every element
        permArr.push(usedChars.slice());   //   so add it as a permutation
    } 
    permute(input);                        //3. compute the permutation of the smaller array
    input.splice(i, 0, ch);                //4. add the original element to the beginning 
                                           //   making input the same size as when we started
                                           //   but in a different order
    usedChars.pop();                       //5. remove the element we pushed
  }
  return permArr                           //return, but this only matters in the last call
};

让我们使用数组 [4,3,2,1] 来追踪详细信息。

当它第一次传入时,我们将取出4,将其推送到usedChars,将其从输入中删除,然后调用permute在 [3,2,1] 上。在这次调用中,我们将把 3 压入usedChars,将其从input,并致电permute关于[2,1]。然后我们将 2 推入usedChars,将其从input, and callpermuteon [1]. Then we push 1 to使用的字符, and remove it frominput`.

这给我们留下了四个深度调用,在步骤 (2) 中: 通道=1 输入=[] 使用的字符=[4,3,2,1]

在步骤 (2) 中,我们将把第一个排列 [4,3,2,1] 推到permArr。然后,继续前进,因为input现在为空,(3) 中的递归调用将简单地返回,在 (4) 中,我们将简单地将 1 添加回输入并从中删除 1usedChars——这个调用返回。

因此,此时,我们已经开始备份递归调用并执行步骤 (4): 通道=2 输入=[1] 使用的字符=[4,3,2]

步骤(4)将执行算法的关键步骤:移动动作。它需要ch=2并将其添加到开始 of input并将其从中删除usedChars。这意味着在步骤(5)之后,我们有:
通道=2 输入=[2,1] 使用的字符=[4,3]

现在看看我们在哪里。我们将 [4,3,2,1] 作为排列推送,然后备份并swapped2 和 1,现在我们将返回递归调用来构建 [4,3,1,2] 并将其添加为排列。之后,我们将退出更多元素,移动更多元素,然后返回排列并添加它们。

回到正题,执行步骤(5)后我们loop。这意味着我们将把 1 推到usedChars并进行递归调用input=[2]。该调用会将 2 推入usedChars创建完整数组 [4,3,1,2] 并将其添加到permArray.

因此,您将通过递归调用来上下循环,构建排列,退出,重建不同的排列,然后退出,直到循环完所有可能的组合。

我希望这有帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试理解 javascript 中 for 循环内的递归 的相关文章

  • GWT - onClick 未触发

    我在表单上有一个非常奇怪的行为 有许多具有内联验证的文本字段 如果内容无效 则会在字段下方显示错误消息 验证在模糊时触发 页面底部有一个 下一步 按钮 单击后 将执行验证 如果一切正常 则提交表单 现在 如果当我单击按钮时强制空白字段具有焦
  • Chrome/Firefox 中双美元符号选择器查询功能的来源是什么?

    Check 这个jsfiddle http jsfiddle net T2PMc 并查看控制台 没有定义 现在 打开一个全新的窗口 然后输入 进入控制台 它定义了一个函数 用于获取与选择器匹配的所有 dom 元素的 类似 jquery 的
  • Three.js - 如何使用姿势估计数据为 3D 模型制作动画

    我正在尝试使用姿势估计坐标来对 Three js 中的装配模型进行动画处理 我正在使用的姿势估计技术提供了视频源中人物的实时 x y z 坐标 我正在尝试使用这些坐标相应地移动 3D 模型 我使用下面的代码 其中一些代码是我在相关问题的答案
  • 重命名从 HTML5 画布创建的图像

    我制作了一个简单的画布并将其另存为图像 我在这段代码的帮助下做到了这一点 var canvas document getElementById mycanvas var img canvas toDataURL image png 并弹出创
  • Javascript - 删除粘贴上的空格

    我有一个最大长度为 10 的输入文本字段 该字段用于澳大利亚电话号码 10 位数字 电话号码通常分为以下语法 12 12345678 如果有人复制上面的内容并将其粘贴到我的输入字段中 显然会留下最后一位数字并保留空格 有没有办法在粘贴到输入
  • 找出 Jquery ajax 请求被重定向到的位置

    所以 我收到了这个ajax请求 请参阅 金发女郎 大约6英尺高 看起来像这样 ajax url http example com makeThing dataType html type POST data something someot
  • 如何限制注册用户尝试投票两次[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 php 编码和网站设计非常陌生 我正在尝试开发一个在线投票系统 只允许注册用户投票 已完成所有操作并且工作正常 但我需要的帮助是
  • 确定是否单击了 Google Chrome 打印预览中的打印/取消按钮

    我一直在使用下面的代码打印我的页面 window print 下图是 Google Chrome 浏览器中的打印预览的样子 它有两个主要按钮 print and cancel 我想知道用户是否点击了print or cancel纽扣 我所做
  • 仅在文件下载完成后设置 cookie。

    我有一个场景 我想告诉用户下载完成并提示关闭按钮 为此 我使用 jquery 插件来连续监视 cookie 以了解下载何时完成 我的问题是我想设置这个cookie fileDownload true and path 下载完成后立即进行 为
  • Google Maps API v3 在地图加载后不会禁用滚轮

    我正在网站上实现谷歌地图 一切都工作得很好 除了地图加载后我似乎无法禁用滚轮 如果我在地图加载之前将选项设置为scrollwheel false 则滚轮将被禁用 但如果我稍后尝试执行此操作 我有一个启用 禁用滚轮的复选框 以下是我在页面加载
  • 删除添加空值的Javascript对象项[重复]

    这个问题在这里已经有答案了 我有一个 JavaScript 对象 finalTitleList Title ffd Iscompleted Id 0 Title fdfmdbk Iscompleted Id 1 Title fdf d Is
  • 单击

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我知道如何用 jquery 做到这一点 但我被 React 困住了 每当用户点击 div 时 我如何聚焦输入字段 你需要有一个onCl
  • 我想在数据表中使用 Div 结构而不是 Table。是否可以?

    我想用数据表 https datatables net 用div结构代替表格 目的是满足设计要求 有什么可能的方法或替代方案吗 不 您将无法执行此操作 Datatables 的核心仅适用于表格元素和子 thead tbody tfooter
  • 为什么闭包编译器不缩短这个?

    我不确定这只是一个错误还是一个预期的功能 基本上 我有这个微小的功能 我现在看到end这里是蓝色的 但这工作得很好 如果我将其重命名为其他名称 我仍然遇到问题 function f a b var start Math min a b va
  • 为车把/余烬定义模板内的数组?

    我在 ember 应用程序中有一个车把模板 它接受一个数组 我目前像这样声明数组 模板 Gd radio input content radioContent value blue JavaScript App IndexControlle
  • 如何在 JS 文件中使用 Github 机密

    我有一个基本的 git 存储库 其中包含用于构建和部署的 github 操作 主要是 HTML 和 TS 文件 但是我必须在一些需要保密的 API 密钥中使用 所以我想办法为他们使用 GITHUB SECRETS 如何在我的 js 或 TS
  • 如何以编程方式将 CSS 定义应用到整个页面?

    我确信该信息已经存在 但我找不到它 对不起 我想使用 JavaScript 创建 CSS 规则 并将它们应用到整个页面 就像它们位于文档头部的样式元素中一样 我不想通过生成 CSS 文本来实现 我想将规则保留为可以更改的实体 JavaScr
  • 矩形描边上的单击事件

    我想仅在矩形的笔划上添加单击事件 并避免在矩形内部单击 下面是代码 var stage new Kinetic Stage container container width 578 height 200 var layer new Kin
  • 动态插入的 jQuery 库加载完成后执行我的 jQuery 脚本

    我通过以下方式在页面上动态插入 jQuery 库
  • 如何使用 PHP 读取/显示 XML

    有没有办法使用 PHP 读取 external xml 来自不同网站的 xml 文件 我知道有一种方法可以使用 JavaScript 读取 XML 但前提是它们都位于同一根目录中 您能否提供有关如何获取 xml 文件的示例 然后阅读以下内容

随机推荐

  • Jenkins-作业失败

    我已经设置了一个 uberSVN 服务器 并运行 Jenkins 以使用 PHP WebWare 控制 SVN 存储库 我已经遇到了问题并寻找解决方案已经好几个小时了 现在我希望这是最后一个 但我没有找到任何答案 Publishing Cl
  • LINQ:如何在多个字段上使用 linq 扩展方法样式进行 JOIN?

    在下面的连接中 我想使用多个字段来进行连接 而不仅仅是一个字段 var join group Join procSums g gt g DeptID ps gt ps key deptID g ps 我发现的所有示例都使用查询样式来执行此操
  • 检测连接的音频设备 iOS

    我正在尝试找出如何检测 iphone ipad ipod 上是否连接了任何音频设备 我知道有关音频路由调用和路由更改回调的所有信息 但这些并没有告诉我有关附加内容的任何信息 它们仅报告音频当前路由的位置 例如 我需要知道当音频通过扬声器传送
  • 如何在 theano 中获得一维卷积

    我能找到的唯一函数是二维卷积此处描述 有没有优化的一维函数 看起来好像这是开发中 我意识到我可以使用conv2d 通过将宽度或高度指定为 1 对于函数conv2d 参数image shape获取长度为 4 的列表 其中包含 number i
  • Node.js:捕获“child_process.spawn”的 STDOUT

    我需要在自定义中捕获stream生成的子进程的输出 child process spawn command args options 例如 var s fs createWriteStream tmp test txt child proc
  • Windows 上的 Bash - exe 文件的别名

    我正在 Windows 上的 Ubuntu 上使用 Bash 这是在 Windows 10 上运行 bash 的方式 我安装了 Creators 更新 Ubuntu 版本是 16 04 我最近在玩 npm node js 和 Docker
  • globalPackagesFolder存储库路径差异

    根据globalPackagesFolderNuGet 文档 它允许您更改默认全局包文件夹的位置 而不是 Users username nuget packages 所以 我发现这是存储包裹的地方 另一方面 repositoryPathNu
  • 使 FetchContent 与 find_package 兼容

    我尝试添加我的项目所需的所有依赖项以通过 CMake 进行编译 这应该会减少其他人第一次编译项目时的开销 为了实现这一点 我尝试使用 FetchContent 到目前为止一切顺利 当我链接生成的目标时 这根本不是问题 但现在我有一个库依赖于
  • 您需要在 GCD 的块内创建 NSAutoreleasePool 吗?

    通常 如果您生成后台线程或在 NSOperationQueue 上运行 NSOperation 则需要为该线程或操作创建 NSAutoreleasePool 因为默认情况下不存在 同样的规则是否适用于放置在 Grand Central Di
  • Jquery 验证插件 - 您可以从选项中启用“热切”验证吗?

    我在项目中使用 Jquery 验证插件 默认情况下 该插件会在单击提交按钮时验证输入 该行为是 惰性的 以便不打扰用户 如果发现错误 验证就会变得 急切 并在用户更正有问题的条目时验证输入 有没有办法通过选项覆盖最初的 惰性 行为 我在文档
  • 如何从时间(小时)中删除前导零

    我想要从 1 到 9 的小时不带前导零 但分钟带零 同时还要在时间上添加 15 分钟 现在 当我输入 1 和 46 时 我得到 02 01 我想得到 2 01 Scanner scan new Scanner System in int h
  • Request.Browser.IsMobileDevice 不适用于 iPadAir2 和 iOS 13.0.1

    I am able to detect iPadAir2 device running on iOS 11 4 using Request Browser IsMobileDevice and it gives me UserAgent i
  • 颁发者证书的过期状态是否会影响主体的过期?

    如果证书颁发者颁发的证书的过期时间发生在颁发者自己的证书过期之后 那么颁发者的证书过期后 颁发的证书是否仍然有效 为了更清楚 让我举个例子 I 发行人 C 颁发的证书 如果我在 2007 年创建了 C 到期日期为 2017 年 我的证书20
  • Leopard 终端(和 iTerm)忽略控制组合键

    I am very used to using Ctrl A Ctrl E Ctrl L etc as shortcuts to operations beginning of line end of line clear terminal
  • 找到不在列表中的最小整数

    我的一位同事使用了一个有趣的面试问题 假设给您一个非常长的 未排序的无符号 64 位整数列表 你如何找到最小的非负整数does not出现在列表中 后续 既然已经提出了明显的排序解决方案 你能比 O n log n 更快地完成它吗 后续 您
  • 查找“nan”并将其替换为数字

    我想替换数组中的数字 3 而不是所有 nan 这是我的代码 train train replace nan int 3 但我的数组没有任何变化 你能指导一下吗 您可以使用np isnan import numpy as np train n
  • 从 ExceptionLogger 引用操作参数

    我想利用新方法来全局记录错误 我写了一个继承的类ExceptionLogger并覆盖Log 方法 然后将其注册为替代品 public class TraceExceptionLogger ExceptionLogger public asy
  • 在 .NET 中创建插件环境的最佳方法

    我读了这篇文章如何在 NET中加载插件 我实在看不出微软的System Addin命名空间有什么高明之处 为什么我不能在 bin 目录中有一个插件文件夹 用户可以将程序集放入其中以实现我设计的界面 然后 我可以使用反射来创建插件类的实例 并
  • Phonegap 在应用程序运行时启用 GPS/位置

    我正在使用 jquery ui maps 和 HTML5 地理位置向用户显示位置列表 我需要利用用户的地理位置 所以 这是用例 用户未启用 GPS 定位服务 用户打开应用程序并导航到调用的视图导航器 地理位置获取用户的位置 应用程序出错并通
  • 尝试理解 javascript 中 for 循环内的递归

    我一直盯着这个问题的答案 甚至在每次迭代中写下变量之类的东西 我只是不明白这里的过程 当我输入控制台日志时 我看到 permute 在到达此行之前被调用 input length 1 次 input splice i 0 ch 当我完全迷失