JavaScript实现字符串全排列的两种方法:递归与非递归

作者:异步漫步时间:2026-10-26 09:31:20浏览:277

本文介绍如何在JavaScript中生成字符串的所有排列。首先通过递归方法利用reduce和map处理字符插入,其次展示基于数组操作的迭代思路,即利用前一步生成的排列结果,在当前字符串的每个空位插入新字符。文章包含完整代码示例及运行输出,适用于理解排列组合算法在前端开发中的应用。

JavaScript实现字符串的所有排列

需求说明

目标是生成并返回给定字符串的所有可能排列组合。

  • 输入参数为一个字符串。
  • 输出结果为一个包含该字符串所有排列情况的数组。

代码实现

const anagrams = str => {
  if (str.length <= 2) {
         return str.length === 2 ? [str, str[1] + str[0]] : [str];
  }
  else{
      return str.split('').reduce((acc, letter, i) =>
    acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), []);
    }
};

运行效果展示

JavaScript实现字符串的所有排列

核心思路解析

主要采用递归思想,排列总数为字符串长度的阶乘。

JavaScript实现字符串全排序

这是一道经典的算法题目。根据排列组合原理,长度为n且不含重复字符的字符串,其全排列的数量为n!(此处暂不考虑去重处理)。

网络上存在多种编程语言的实现方案,但专门针对JavaScript的实现相对较少(这或许反映了前端开发者在算法领域的关注度)。此外,常见的实现多依赖于递归方法。本文尝试提供一种非递归的JavaScript实现方式。

首先阐述基本思路:对于单个字符的字符串,其全排列数量仅为1。

对于两个字符的字符串(例如ab),全排列数量为2,即ab和ba。那么,我们是如何得到这些结果的?

具体推导过程如下:

  • 第一步:取出字符a,此时a的前后形成两个空位,示意如下:0 a 0。
  • 第二步:将字符b分别插入到这两个空位中,从而得到ba和ab。
  • 第三步:对于双字符情况,过程至此结束。

那么,面对三个字符abc的情况,该如何处理?

基本逻辑不变,但基于前一步两个字符已全排列的结果进行扩展。

  • 第一步:取之前生成的排列ba,它产生了三个空位,示意如下:0 b 0 a 0。
  • 第二步:将剩余字符c分别插入这三个空位,得到cba、bca和bac。
  • 接着处理另一个前序排列ab,重复上述步骤,将c插入其产生的空位,得到cab、acb和abc。

如果是四个字符abcd组成的字符串呢?

逻辑一致:利用三个字符产生的所有排列结果,为每个排列生成4个空位,然后将字符d分别插入这些空位中。

至此,算法思路阐述完毕,接下来通过代码进行实现。

function myPermutation(str){
        // 空字符串直接返回吧
	if(str.length === 0){
		console.log('The string you input have No length!');
		return;
	}
        // 一个字符也不用运算
	if(str.length === 1){
		console.log('The result array is: ' + str, '-&- The array length is: ' + str.length);
		return;
	}
        // 长度2以上的开始计算
        /* 先把字符串转成数组,因为js里关于字符串的函数不多,而关于数组的函数很多,所以中间步骤我们都用数组处理,比较方便 */
 
	var arrayStr = str.split('');
        /* 定义一个中间数组,作为每次大循环的根基。比如,你开始拿第3个字符去填充空位,那前2个字符的全排列就已经都存储在中间数组里了 */
        // 你开始拿第4个字符去填充空位,那前3个字符的全排列就已经都存储在中间数组里了
 
	var transArray = [];
        /* 先把字符串的第1个字符存入中间数组,这是我们盖高楼的地基。此字符产生的两个空位,我们拿第2个字符开始去填充 */
	transArray.push(arrayStr[0]);
        // 定义一个存储最终结果的数组,作为返回值
	var resultArray = [];
        /* 第一层循环,从第2个字符开始,每次向字符串后取一个字符,往 中间数组 的每个字符串的 空位 里插 */
	for(var i = 1; i < arrayStr.length; i++){
		resultArray = [];
            // 每次新取到的字符
		var addChar = arrayStr[i];
            /* 第二层循环,取一个 中间数组里 用以形成空位的 字符串,中间数组的长度就是此新字符前面的所有字符形成的全排列个数 */
		for(var j = 0; j < transArray.length; j++){
                // 依次取中间数组里的串
			var toBeInsertStr = transArray[j];
                // 用空格分割字符串,从而产生空位
			var toBeInsertStrArray = toBeInsertStr.split('');
                // 第三层循环,将取到的新字符分别放到空位上形成字符串,有多少空位就循环几次
			for (var k = 0; k <= transArray[j].length; k++){
				tempArray = toBeInsertStrArray.concat();
                // 用splice函数处理,表示将字符填入空位
				var insertedArray = toBeInsertStrArray.splice(k, 0, addChar);
                    // 刚才是数组操作,现在转成字符串
				var transArrayItem = toBeInsertStrArray.join('');
                    // 将字符串压入结果数组
				resultArray.push(transArrayItem);
				toBeInsertStrArray = tempArray.concat();
			}
		}
		transArray = [];
		transArray = resultArray.concat();
	}
	console.log('The result array is: ' + resultArray, '-&- The array length is: ' + resultArray.length);
}
 
myPermutation('');
myPermutation('a');
myPermutation('ab');
myPermutation('abc');

程序运行结果如下:

The string you input have No length! The result array is: a -&- The array length is: 1 The result array is: ba,ab -&- The array length is: 2 The result array is: cba,bca,bac,cab,acb,abc -&- The array length is: 6

总结

以上为个人经验分享,希望能提供有益参考,也希望大家多多支持本站。

作者最新文章