07、JS实现:用回溯法实现数组全排列的算法(一步一步剖析,很详细)

回溯法实现数组全排列的算法

  • Ⅰ、回溯法实现数组全排列:
    • 1、题目描述:
    • 2、解题思路:
    • 3、实现代码:
  • Ⅱ、小结:

Ⅰ、回溯法实现数组全排列:

1、题目描述:

给定⼀个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输⼊: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

2、解题思路:

以 [1,2,3] 为例,根据回溯思想,我们的逻辑是:
先从 [1,2,3] 选取⼀个数。
然后继续从 [1,2,3] 选取⼀个数,并且这个数不能是已经选取过的数。
重复这个过程直到选取的数字个数达到了 3。


可能存在的问题:
其一、如何确保这个数不能是已经选取过的数?
答:我们可以直接在已经选取的数字中线性查找,也可以将已经选取的数字中放到 hashset 中,这样就可以在
O(1)的时间来判断是否已经被选取了,只不过需要额外的空间;

3、实现代码:

其一、代码为:


// 此时的 list 是空数组、tempList 是空数组、nums 是没有重复数字的数组;
const backtrack = (list, tempList, nums) => {if (tempList.length === nums.length) return list.push([...tempList])for (let i = 0; i < nums.length; i++) {// 此时 continue 的作用:若 if() 满足条件,则会跳出本次的 for 循环;if (tempList.includes(nums[i])) continuetempList.push(nums[i])backtrack(list, tempList, nums)tempList.pop()}
}const permute = (nums) => {const list = []backtrack(list, [], nums)return list
}// 此时的输出结果为:[ [ 1, 2, 3 ], [ 1, 3, 2 ], [ 2, 1, 3 ], [ 2, 3, 1 ], [ 3, 1, 2 ], [ 3, 2, 1 ] ];
permute([1, 2, 3])
执行  backtrack(list, [], nums)  函数后代码执行的过程(即:执行 backtrack([], [], [1,2,3]) 函数):注意:里面涉及多个循环嵌套递归,每次递归的出口为 tempList.length === nums.length,循环的出口为 for() 循环结束;第一层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[0]) 代码后,tempList 数组为 [1];backtrack(list, tempList, nums) 执行代码为:backtrack([], [1], [1,2,3])第二层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第二层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[1]) 代码后,tempList 数组为 [1,2];backtrack(list, tempList, nums) 执行代码为:backtrack([], [1,2], [1,2,3])第三层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[2]) 代码后,tempList 数组为 [1,2,3];backtrack(list, tempList, nums) 执行代码为:backtrack([], [1,2,3], [1,2,3])if (tempList.length === nums.length) return list.push([...tempList]),list 的数组为[[1,2,3]];执行 tempList.pop() 代码后,tempList 数组为 [1,2];执行 tempList.pop() 代码后,tempList 数组为 [1];第二层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[2]) 代码后,tempList 数组为 [1,3];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3]], [1,3], [1,2,3])第三层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[1]) 代码后,tempList 数组为 [1,3,2];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3]], [1,3,2], [1,2,3])if (tempList.length === nums.length) return list.push([...tempList]),list 的数组为[[1,2,3],[1,3,2]];执行 tempList.pop() 代码后,tempList 数组为 [1,3];第三层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;			执行 tempList.pop() 代码后,tempList 数组为 [1];执行 tempList.pop() 代码后,tempList 数组为 [];第一层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[1]) 代码后,tempList 数组为 [2];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2]], [2], [1,2,3])第二层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[0]) 代码后,tempList 数组为 [2,1];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2]], [2,1], [1,2,3])第三层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[2]) 代码后,tempList 数组为 [2,1,3];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2]], [2,1,3], [1,2,3])if (tempList.length === nums.length) return list.push([...tempList]),list 的数组为[[1,2,3],[1,3,2],[2,1,3]];执行 tempList.pop() 代码后,tempList 数组为 [2,1];执行 tempList.pop() 代码后,tempList 数组为 [2];第二层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第二层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[2]) 代码后,tempList 数组为 [2,3];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2],[2,1,3]], [2,3], [1,2,3])第三层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[0]) 代码后,tempList 数组为 [2,3,1];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2],[2,1,3]], [2,3,1], [1,2,3])if (tempList.length === nums.length) return list.push([...tempList]),list 的数组为[[1,2,3],[1,3,2],[2,1,3],[2,3,1]];执行 tempList.pop() 代码后,tempList 数组为 [2,3];第三层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;			执行 tempList.pop() 代码后,tempList 数组为 [2];执行 tempList.pop() 代码后,tempList 数组为 [];第一层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[2]) 代码后,tempList 数组为 [3];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2],[2,1,3],[2,3,1]], [3], [1,2,3])第二层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[0]) 代码后,tempList 数组为 [3,1];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2],[2,1,3],[2,3,1]], [3,1], [1,2,3])第三层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[1]) 代码后,tempList 数组为 [3,1,2];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2],[2,1,3],[2,3,1]], [3,1,2], [1,2,3])if (tempList.length === nums.length) return list.push([...tempList]),list 的数组为[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2]];执行 tempList.pop() 代码后,tempList 数组为 [3,1];第三层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;执行 tempList.pop() 代码后,tempList 数组为 [3];第二层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[1]) 代码后,tempList 数组为 [3,2];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2]], [3,2], [1,2,3])第三层循环,在 i=0 的情况下:if (tempList.includes(nums[i])) continue 的判断不成功;执行 tempList.push(nums[0]) 代码后,tempList 数组为 [3,2,1];backtrack(list, tempList, nums) 执行代码为:backtrack([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2]], [3,2,1], [1,2,3])if (tempList.length === nums.length) return list.push([...tempList]),list 的数组为[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]];执行 tempList.pop() 代码后,tempList 数组为 [3,2];第三层循环,在 i=1 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;第三层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;			执行 tempList.pop() 代码后,tempList 数组为 [3];第二层循环,在 i=2 的情况下:if (tempList.includes(nums[i])) continue 的判断成功,因此直接跳出此次的 for() 循环的过程;执行 tempList.pop() 代码后,tempList 数组为 [];因此,最后 list 的输出结果为:[ [ 1, 2, 3 ], [ 1, 3, 2 ], [ 2, 1, 3 ], [ 2, 3, 1 ], [ 3, 1, 2 ], [ 3, 2, 1 ] ],
而 tempList 的输出结果为:[];

其二、截图为:

在这里插入图片描述

Ⅱ、小结:

其一、哪里有不对或不合适的地方,还请大佬们多多指点和交流!
其二、若有转发或引用本文章内容,请注明本博客地址(直接点击下面 url 跳转) https://blog.csdn.net/weixin_43405300,创作不易,且行且珍惜!
其三、有兴趣的话,可以多多关注这个专栏(Vue(Vue2+Vue3)面试必备专栏)(直接点击下面 url 跳转):https://blog.csdn.net/weixin_43405300/category_11525646.html?spm=1001.2014.3001.5482

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/776437.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flowable-ui后台显式非中文

把flowable-ui的war包发布后&#xff0c;后台界面显示的是非中文 用的是6.7.2版本&#xff0c;经过了解该版本是有国际化配置文件的&#xff0c;支持中文 猜测可能是浏览器语言导致未显示中文&#xff0c;在控制台输入navigator.language&#xff0c;查看到果然是英文 解决方案…

如何制作蛋糕店小程序_开启您的蛋糕店小程序之旅

甜蜜滋味&#xff0c;一触即达——开启您的蛋糕店小程序之旅 在这个快节奏的时代&#xff0c;人们对美食的追求从未停歇。尤其是那些色香味俱佳、口感细腻的蛋糕&#xff0c;更是成为了许多人生活中的小确幸。然而&#xff0c;忙碌的工作和生活常常让我们无法亲自前往蛋糕店&a…

大型网络游戏设计与AI赋能-6

接上文&#xff01;&#xff01;! 所以最后我们会有一个Game design的分析。这个分析主要是在游戏类型&#xff0c;最后这个游戏会发布在什么平台上&#xff0c;游戏的玩法具体是什么样子的&#xff0c;需要提供给玩家哪些比较特殊的玩家体验等等。列出来这4项是一定要去考虑的…

经典机器学习模型(九)EM算法的推导

经典机器学习模型(九)EM算法的推导 1 相关数据基础 1.1 数学期望 1.1.1 数学期望的定义 根据定义&#xff0c;我们可以求得掷骰子对应的期望&#xff1a; E ( X ) X 1 ∗ p ( X 1 ) X 2 ∗ p ( X 2 ) . . . X 6 ∗ p ( X 6 ) 1 ∗ 1 6 2 ∗ 1 6 1 ∗ 1 6 3 ∗ 1 6 …

PostgreSQL11 | Windows系统安装PostgreSQL

本教程选取与参考书籍《PostgreSql11 从入门到精通》&#xff08;清华大学出版社&#xff09;的11大版本最新小版本11.22的安装作为教程案例 下载 下载PostgreSQL installer 下载到本地 安装 运行安装引导器 中国地区语言选项&#xff08;暂时&#xff09; Chinese(Simplifie…

测试开发工程师(QA)职业到底需要干些什么?part7:硬件测试工程师QA

概述 硬件测试工程师QA主要负责确保硬件产品在设计、制造和交付过程中的质量和性能。主要任务是进行测试、验证和分析硬件系统、组件和设备&#xff0c;以确保其符合规格和质量标准。下面是硬件测试工程师QA在其工作中常涉及的一些方面&#xff1a; 测试计划和策略&#xff1a…

EMCC13.5安装配置手册(详细版)

ORACLE OEM13.5安装配置详细文档 包含详细的安装配置&#xff0c;常见的错误和解决办法&#xff0c;已经OEM添加集群和主机等可能遇到的问题和解决办法 一、数据库基础环境安装 版本&#xff1a;Oracle Database 19c Enterprise Edition Release 19.3.0.0.0 - 64bit Product…

Mybatis的动态SQL~

MyBatis有一个强大特性就是它的动态SQL。在实际项目开发中&#xff0c;经常需要根据不同条件拼接SQL语句&#xff0c;拼接时还要确保不能忘了必要的空格&#xff0c;有时候还要注意省掉列名列表最后的逗号...等等。在使用JDBC 或其他类似持久层框架操作数据库时&#xff0c;处理…

全国美食博主都在天水:一碗麻辣烫,如何在互联网热辣滚烫?

从淄博到哈尔滨&#xff0c;地方文旅此前从未想到过&#xff0c;自己与“一夜爆火”的距离居然这么近&#xff1b; 而等到从哈尔滨再到天水时&#xff0c;地方文旅的应对甚至已经开始轻车熟路了起来。 热闹之下&#xff0c;难免有几个问题需要细思&#xff1a;为什么从2023年到…

【探索C++】友元

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…

nvm 报错 Could not retrieve https://npm.taobao.org/mirrors/node/index.json.

报错信息如下 原因 因为淘宝的镜像域名更换&#xff0c;npm.taobao.org域名HTTPS证书到期更换为npmmirror.com&#xff0c;故此导致安装依赖报错 解决 1、进入nvm安装目录&#xff08;例如&#xff1a;C:\Users\默认账户\AppData\Roaming\nvm&#xff09;中找到settings.txt…

第八届信息系统与数据采集国际会议(ICISDM 2024)即将召开!

第八届信息系统与数据采集国际会议&#xff08;ICISDM 2024&#xff09;将于2024年6月24日至6月26日在美国第二大城市——洛杉矶召开。此次会议不仅展现了世界各地的科研专家们围绕着信息系统和数据采集所展开的最新的科学研究结果&#xff0c;而且也为来自不同地区的代表们提供…

如何进行 SEO 竞争对手分析

SEO &#xff08;搜索引擎优化&#xff09;的世界是一个庞大、复杂且竞争激烈的地方。如此之多&#xff0c;以至于你可能会觉得自己永远无法超越你的竞争对手。 但不要绝望&#xff1a;对竞争对手的 SEO 策略进行一些监视会大有帮助。 它涉及评估他们的关键字定位、反向链接配…

【论文阅读】Faster Neural Networks Straight from JPEG

Faster Neural Networks Straight from JPEG 论文链接&#xff1a;Faster Neural Networks Straight from JPEG (neurips.cc) 作者&#xff1a;Lionel Gueguen&#xff0c;Alex Sergeev&#xff0c;Ben Kadlec&#xff0c;Rosanne Liu&#xff0c;Jason Yosinski 机构&#…

redis的设计与实现(四)——单机数据库特性

1. 前言 我们前面了解了redis的数据结构&#xff0c;对象。但是redis对于这些对象的使用和管理策略需要也熟记于心&#xff0c;这篇文章我们就了解一下吧。 2. 类型检查和命令多态 DEL,EXPIRE,RENAME,TYPE,OBJECT 可以对任何数据类型执行SET,GET,APPEND,STRLEN&#xff0c;等…

【nodejs ubuntu】nodejs版本过老的更新方法

使用apt方法安装的node.js版本过于老了&#xff0c;以至于我没法用npm下载hexo 下面是更新方法 参考了这篇文章 然后就可以成功安装了

蓝桥杯算法赛(二进制王国)

问题描述 二进制王国是一个非常特殊的国家&#xff0c;因为该国家的居民仅由 0 和 1 组成。 在这个国家中&#xff0c;每个家庭都可以用一个由 0 和 1 组成的字符串 S 来表示&#xff0c;例如 101、 000、 111 等。 现在&#xff0c;国王选了出 N 户家庭参加邻国的庆典…

PMP考试难不难,通过率怎样?

PMP考试自从新考纲调整后有几次考试难度是非常高的&#xff0c;那段时间我也看网上好多机构通过率都不咋地&#xff0c;当时也是因为官方的出题难度稍高&#xff0c;还组织了免费的重考&#xff0c;也是后来逐渐开始归于平常了吧&#xff0c;直到现在都是我认为比较简单的选择题…

【Qt】QDialog对话框

目录 一、概念 二、对话框的分类 2.1 模态对话框 2.2 非模态对话框 2.3 混合属性对话框 三、消息对话框QMessageBox 四、颜色对话框QColorDialog 五、文件对话框QFileDialog 六、字体对话框QFontDialog 七、输入对话框QInputDialog 一、概念 对话框是GUI程序中不可或…

Unity角色多人同步

1.位置同步和状态同步&#xff1a;需要同步的节点上挂载脚本&#xff1a; gameObject.AddComponent<SyncTransform>(); ; //同步gameObject.GetComponent<SyncTransform>().syncId SyncUtilFunc.GetRoleSyncId(PlayerData.Instance.PlayerId); //同步gameObject.G…