JS 字符串全排列算法及内存溢出

回溯算法本质:决策树建模与剪枝思维 回溯算法是一种基于决策树的系统性搜索方法,其核心在于将问题抽象为‘状态定义—选择枚举—约束表达’三步建模过程。它并非单纯依赖递归实现,而是体现‘试错+撤回’的问题求解本能;剪枝也不是性能优化技巧,而是对可行性约束的精准翻译。该思想广泛应用于组合、排列、子集、N皇后等经典问题,并延伸至编译器寄存器分配、芯片布线、基因序列比对及AI模型轻量化等工程场景。掌握回溯,关键在于理解决策树结构如何由问题约束决定,以及如何将业务规则转化为代码中的剪枝逻辑。 阅读详情


问题

给定字符串,求出所有由该串内字符组合的全排列。所包含的字符不重复。

输入:"abc"
输出:["abc","acb","bac","bca","cab","cba"]

我在实现算法时遇到了一个问题,至今无法解决。但是全排列算法又很重要,所以写这篇文章记录一下。

算法一:递归

算法思想:

  1. 当字符串长度为1时,输出该字符串;
  2. 当长度大于1时,取字符串的首字母,求出长度-1的串的全排列,将首字母插入每一个排列的任意位置。

    算法实现:

function permutate(str) {
    //保存每一轮递归的排列结果
    var result = [];
    //初始条件:长度为1
    if (str.length == 1) {
        return [str]
    } else {
        //求剩余子串的全排列,对每个排列进行遍历
        var preResult = permutate(str.slice(1));
        for (var j = 0; j < preResult.length; j++) {
            for (var k = 0; k < preResult[j].length + 1; k++) {
                //将首字母插入k位置  
                var temp = preResult[j].slice(0, k) + str[0] + preResult[j].slice(k);
                result.push(temp);
            }
        }
        return result;
    }
}

算法应该不难理解吧。但是当传参的字符串是"abcdefghijkl"时,排列用到的空间是12!=479001600,过大的内存占用导致内存溢出。如果你是在自己的PC上执行,那么可以使用node --max-old-space-size=8192来修改内存。但是我需要在Codewars上执行,所以无法修改内存。于是我想的办法是利用尾递归优化。呵呵,Node的尾递归优化?不管了,先试试吧。

算法二:尾递归

function permutate(str,result) {
    'use strict';
    let tempArr = [];
    //终止条件str长度为0
    if (str.length == 0) {
        return result
    } else {
        //第一次递归时,插入首字母
        if(result.length === 0){
            tempArr.push(str[0]);
        }else{
            for (let i = 0; i < result.length; i++) {
                let item = result[i];
                let itemLen = item.length;
                for (let j = 0; j < itemLen+1; j++) {
                    let temp = item.slice(0, j) + str[0] + item.slice(j);
                    tempArr.push(temp);
                }
            }
        }
        //递归截取了第一个字符的子串
        return permutate(str.slice(0),tempArr);
    }
}
permutate("abcdefghijkl",[]);

函数的第一个参数是本次递归的字符串,第二个参数是前x个字符的全排列结果。
思路是:

  1. 每次取当次递归串的第一个字母;
  2. 若第二个参数长度为0说明是第一次递归,则初始化本次结果为[首字母]。然后将首字母从递归串中剔除,剩余串传给下一次递归;
  3. 之后每一次递归,都取递归串的首字母,将其插入前x个字符的全排列的所有位置,求出x+1个字符的全排列;
  4. 递归直到第一个参数为空串,则第二个参数为字符串所有字符的全排列。

    可能不太好理解,不过知道这是尾递归就行了。虽然尾递归在ES6的严格模式中才有效,但是,我加上'use strict';后仍然无效。事实上我认为并不是函数调用栈的溢出,而是存放变量的堆溢出。所以,大概是无解了吧。毕竟全排列不管怎么样,空间复杂度都是O(n!)的。

算法三:循环

最后再贴个循环的代码吧,也是没什么用,就当扩展思路了。

function perm(str) {
    let result = [],tempArr = [];
    let subStr = str;
    while (subStr.length !== 0) {
        if (result.length === 0) {
            result.push(str[0]);
        } else {
            for (let i = 0; i < result.length; i++) {
                let item = result[i];
                let itemLen = item.length;
                for (let j = 0; j < itemLen+1; j++) {

                    let temp = item.slice(0, j) + subStr[0] + item.slice(j);
                    tempArr.push(temp);
                }
            }
            result = tempArr;
            tempArr = [];
        }
        subStr = subStr.slice(1);
    }
    return result;
}
文章来源: 北大青鸟学校 HD089455
js实现字符全排列算法的简单方法 下面小编就为大家带来一篇js实现字符全排列算法的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 立即下载

相关推荐

JS实现的数组全排列输出算法

本文实例讲述了JS实现的数组全排列输出算法。分享给大家供大家参考。具体分析如下: 这段js代码对数组进行全排列输出,改进了一些老的代码 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。 function permute(input) { var permArr = [], usedChars = []; function main(input){ var i, ch; for (i = 0; i < input.length; i++) { ch = inp

Java String字符串类型导致内存溢出的分析和解决方案 (使用string += 为什么会导致内存占用过高?)

1. String类型变量操作时为何容易内存溢出 在实际工程或者算法题练习中,我们有时候会遇到String类型变量导致内存溢出或者占用过高。 原因是String类型在java中是immutable(不可直接修改)的变量,所以对于字符串我们是不能直接修改的,只能重新生成占据新的栈空间。 String[] words = s.split(" "); for (int i = 1; i < words.length; i++) { str += " " + words[i]; } s是一个空格分隔的超

TylerDu的博客 2万+

详解Unity中的粒子系统Particle System (三)

上一篇我们详细讲解了有关主模块的全部内容,已经对粒子系统的基本运作有了足够的了解,本篇就来讲一下被粒子系统默认启用的Emission、Shape、Renderer模块又在粒子系统中扮演着怎么样的作用吧。

梦小天幼的博客 1万+

35-[内存溢出]&[内存泄漏]

内存溢出 一种程序运行出现的错误 当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误 var obj = {} for (var i = 0; i < 10000; i++) { obj[i] = new Array(10000000) console.log('-----') } 内存泄漏 占用的内存没有及时释放 内存泄漏积累多了就容易导致内存溢出 常见的内存泄漏: 1.意外的全局变量 function fn() { a = 10 console.log(a) } f

述安的博客 187

扫地机器人:从仿真到决策,一个完整SLAM导航系统的自研之路

本文详细记录了从零开始自研扫地机器人SLAM导航系统的全过程,涵盖ROS-Gazebo仿真系统搭建、地图预处理优化、全覆盖规划算法迭代等关键技术。通过三次算法升级,最终实现92%的清洁效率,并分享DWA调参、状态机设计等实战经验,为开发者提供从仿真到落地的完整解决方案。

weixin_29053695的博客 352

shader多图叠加变换

shader Shader "Paint3D/AddTexture" { Properties { _MainTex ("Main Texture", 2D) = "white" {} _MainColor("Main Color", Color)=(1,1,1,1) _AddTex0 ("Texture0", 2D) = "white" {} _AddTex1 ("Texture1", 2D) = "white" {} .

李长江的博客 908

js 实现全排列

js 实现全排列

L的博客 995

基于本地知识库的智能问答系统架构

智能问答系统的核心可以分为4部分。1)知识库构建。2)检索。3)后处理。4)推理。知识库构建:知识库中可以包含多个向量数据库和知识图谱等,核心是怎么建立索引,使得检索时能够将与问题相关的知识给检索出来。检索:从知识库中的多个库或者知识图谱中检索出与问题相关的信息。后处理:从知识库中检索出来的信息可能是冗余的,而且可能不符合我们希望的格式要求,因此,我们需要对这些数据进行过滤,格式化等操作。推理: 基于检索出来的知识进行推理,让输出能够回答用户的问题,目前主要使用大模型进行推理。

qq_44993593的博客 1709

算法(一):全排列实现与尾递归

将n个元素按照一定的顺序排列起来,求出排列的所有组合。算法分析, 假定n个元素的全排列组合为F(n) 1. n = 1,只有一种组合(1),即F(n) = [(1)]; 2. n = k时,只需要与n = k - 1时形成的全排列组合F(k - 1)一一组合排列即可,增加的元素为 (k - 1) * F(k - 1),故现在的组合数量为 (k - 1) * F(k - 1) + F(k - 1)

甘焕的博客 736

C++ bitset总结

数据结构bitset 术语:某1位置位是置1,某一位复位是某一位清零。 文章目录数据结构bitset一、3种初始化方式二、位访问三、位操作四、 位集操作总结实战练习 一、3种初始化方式 bitset<32> tmp; //默认构造函数,默认全0。 bitset<32> tmp(-1); //从整形数构造 bitset<32> tmp("101"); //从包含1和0的字符串构造 二、位访问 bitset<32> tmp(256)

qq_43807092的博客 719

GX Works2系统启动失败排查指南:从环境配置到修复方案

在工业自动化与PLC编程调试中,软件启动异常是常见的工程痛点。当开发工具因系统环境配置不当而频繁报错时,往往不是简单的重启能解决的。运行库缺失、区域设置错误、临时目录失效或系统服务被禁用,都可能导致编程软件无法完成初始化流程。掌握从基础环境检查到系统组件修复的系统性排查思路,是提升工控开发效率的关键能力。本文从软件初始化原理出发,结合Windows系统维护实践,梳理一套适用于工业软件启动故障的通用诊断方法,并自然聚焦到三菱GX Works2常见启动失败问题的实际处理,帮助工程师快速定位并解决环境性故障,保障

weixin_42567046的博客 454

如何用 ipatool 从 App Store 下载 IPA 文件:认证、取包、拿历史版本一次讲清

想分析某个 App 的某个旧版本,却发现手机里只能装到最新版,网页上也查不到旧版包的下载入口?ipatool 就是为解决这个问题做的命令行工具:它直接调用 App Store 的接口,在终端里完成搜索、登录、下载 IPA 包(iOS 应用安装包)的完整流程,还能列出历史版本并下载其中任意一版。Windows、Linux、macOS 三个平台行为一致,全程不需要 iOS 设备。 App Store

gitblog_00573的博客 423

白话FOC控制中各环节的参数的意义与如何设置参数

FOC参数整定是控制系统的关键环节,如同驯马需要调节"智能马鞍"。核心参数分为三类:电流环参数(P/I/D)决定响应速度和稳定性,速度环参数需慢于电流环5-10倍带宽,系统参数(极对数、电阻等)是电机固有属性必须准确设置。调参心法:由内而外先调电流环,遵循先P后I慎用D原则,内环带宽必须大于外环。利用自动辨识工具,通过听觉(滋滋声表示P过大)和波形观察来微调,最终实现精准控制。

汽车软件开发 356

全排列 -深度优先算法中的剪枝问题

在深度优先算法中,如果遇到需要剪枝的问题,如果你不剪,必然会爆内存,爆栈。 看以下的题目: 给出一个字符串S(可能有重复的字符),按照字典序从小到大,输出S包括的字符组成的所有排列。例如:S = "1312", 输出为: 1123 1132 1213 1231 1312 1321 2113 2131 2311 3112 3121 3211 Input...

weixin_30746117的博客 239

重回童年的经典系列☀️|【炸弹人小游戏】制作过程+解析 | 收藏起来跟曾经的小伙伴一起梦回童年!

Unity,小游戏开发。 本篇文章对童年经典小游戏——炸弹超人进行制作和解析。不知道有没有勾起你童年的回忆呢!快来和我一起制作这个童年经典的小游戏吧! 敬请品尝!

努力前行,总会成为自己心中的那道光 13万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

leetcode - JS

文章目录全排列问题图形旋转字母异位词分组幂运算 pow(x,n) 全排列问题 function permuteback(nums, index, arr) { //全排列 if (nums.length-1 == index) { //输出 var n = []; nums.forEach(element => { n.push(element); }); arr.push(n); } else { //如果数据不重复 不需要 visit[] 查看 var v

qq_40701470的博客 237

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

多维聚合实战:超越GROUP BY的高维数据分析方法论

多维聚合是现代数据分析的核心能力,本质是支撑任意维度组合下即时获取汇总结果的立方体(Cube)计算范式。其技术原理涉及关系代数局限性、分组基数爆炸、内存哈希瓶颈及维度建模语义断裂等深层挑战。相比基础SQL聚合,它更强调预计算策略、MPP引擎优化、流式状态管理与语义层抽象四层协同,具备显著的工程可扩展性与业务语义鲁棒性。典型应用场景涵盖销售漏斗分析、用户行为归因、跨区域-时间-产品库存预测等复杂BI需求。本文聚焦Multi-Dimensional Aggregation与聚合语义两大核心热词,系统拆解从模型设

weixin_30258901的博客 434

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

多维聚合中的数据操纵:破解稀疏性与语义漂移陷阱

多维聚合是BI报表、用户行为分析和时序统计的核心技术,其本质是将二维表格升维为逻辑立方体结构。这一过程引发关键挑战:数据天然稀疏性导致缺失值(NaN)与零值(0)语义混淆,而ROLLUP/CUBE等分组操作又引入GROUPING标记带来的语义漂移风险。正确处理缺失组合、层级汇总和跨维度比率,直接决定指标口径一致性与AI特征工程可靠性。本文聚焦Pandas pivot_table、SQL GROUPING SETS及Doris/ClickHouse物化视图三大技术栈,详解fill_value策略、reinde

weixin_30239339的博客 390

【JS数据算法】字符串的排列

最近在牛客网上学习与练习数据算法,整理了一些有关数据算法相关知识,如果有什么不足或错误请指出,互相学习,共同进步

weixin_46857470的博客 770

剑指 Offer 38. 字符串的排列 js

剑指 Offer 38. 字符串的排列 输入一个字符串,打印出该字符串中字符的所有排列。 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。 示例: 输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"] 输入:s = "aab" 输出:["aba","aab","baa"] 解题思路: 分析题目,我们可以很容易地看出可以使用遍历的方法进行求解,即为树形问题,使用回溯法。在该题中,题目没有说明字符串中字符不重复,故我们需要对数组进行排列去重。

一只蒻蒻的博客 411

js 字符串的全排序

实现全排序 function fullpermutate(str) { var result = []; if (str.length > 1) { //遍历每一项 for (var m = 0; m < str.length; m++) { //拿到当前的元素 var left = str[m]; //除当前元素的其他元素组合 ...

me_never的博客 3066

Javascript 字符串全排列组合方法实现

Javascript 字符串全排列组合方法实现一、目标:二、思路:三、代码: 一、目标: 把一个字符串中的字符重新排列生成新的字符串,例如, abc 总共有6种排列 (abc, acb, bac, bca, cab, cba)。 二、思路: 本文章只研究全排列的情况,比如,还是 abc 字符串,3个字符,则总共的排列组合方式应该有 n! 种,此处的 n 为3,则计算出来应该是6种。本文采用递归方...

xie_sining的博客 5844

JS全排列的几种算法

问题描述: 给定一个字符串,输出该字符串所有排列的可能。如输入“abc”,输出“abc,acb,bca,bac,cab,cba”我们 都知道3个数字全排列一共有C3^3=6种方法,那么怎么实现呢? 方法一:(递归) /* 全排列(递归交换)算法 1、将第一个位置分别放置各个不同的元素; 2、对剩余的位置进行全排列(递归); 3、递归出口为只对一个元素进行全排列。 */ function swap(arr,i,j) { if(i!=j) { v...

yiyueqinghui的博客 2159

在 JavaScript 中生成字符串的所有组合 (字符排列)

本教程介绍如何开发一个字符串排列生成工具,通过HTML、CSS和JavaScript实现。文章首先解释了排列的概念及其与组合的区别,并重点讲解了回溯算法的实现原理,包括处理重复字符和复杂度分析。随后详细展示了前端实现步骤:HTML构建输入/输出界面,CSS设计现代化卡片布局,JavaScript实现核心递归算法。最后强调了输入验证和性能优化的必要性(建议限制输入长度≤9字符),确保工具实用且高效。全文提供了完整的代码结构和实现思路,适合具备基础前端知识的开发者学习。

weixin_42107409的博客 941

JS实现文字溢出隐藏效果

由于项目原因,经常需要使用到canvas来将dom生成为图片供用户保存,但canvas的css属性(例如本文实现的文字溢出隐藏效果)支持并不全面,所有有些功能只能用JS来实现了。用JS循环判断填充文本后的元素长度是否超过阈值,如超过就进行调整,缩短一些文本的长度。

凌晨不睡觉 810
上一篇: Flutter beta 1 重磅发布:开发精美的原生应用
下一篇: JavaScript函数知识点梳理
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值