JavaScript数组全排列生成


在本题中,要求我们使用JavaScript生成给定数组的所有可能的排列,从暴力方法到优化方案。

什么是JavaScript数组?

如果您熟悉其他编程语言,例如C、C++或Java,您一定听说过“数组”这个术语。

在编程中,数组是在一个单元下收集的相似数据元素。

现在,一个重要的问题出现了:如果数组在所有语言中通常都是相同的,那么JavaScript是如何使数组更独特和易于使用的呢?

让我们了解JavaScript中数组的整体工作原理。

数组是一个存储多个元素的对象。由于数组也是一个对象,它具有一些属性和方法,使在JavaScript中处理数组更容易。

示例

以下是JavaScript中定义数组的语法:

const arrayExample  = [ 10 , 30 , 50 ,60 ];
console.log(arrayExample);

输出

[10, 30, 50, 60]

什么是JavaScript数组的排列?

数组的排列是指对数组中存在的元素进行洗牌和排序。它使用数组作为其输入源,生成元素的所有可能方式或排列。

如果我们在JavaScript中有一个包含n个元素的数组,它将生成n!种可能的元素排序和输出方式。

元素的排列是解决问题陈述的核心,其中输入和输出可以可视化为:

const arr = [ 1 , 2 , 3 ] ;

// generate all permutation 

[ 1 , 2 , 3 ] 
[ 1 , 3 , 2 ]
[ 2 ,1 , 3  ]
[ 2 , 3 , 1 ]
[ 3 , 1 , 2 ]
[ 3 , 2 , 1 ]

查找排列背后的逻辑

查找数组元素排列的逻辑类似于在数学中查找排列,我们将从编码的角度来看它,例如,取一个数组[1,2,3],我们将重复执行一些步骤。

例如,我们将分离数组的第一个元素,并让它按时间顺序与其他已经存在的元素组合,结果为[1, 2, 3]。然后,相同的分离元素与时间顺序的交换顺序(2,3)组合,产生新的排列集[1, 3, 2]。

以下逻辑重复执行,直到数组长度耗尽,利用递归技术在帮助下生成具有一个核心分离元素的不同排列步骤。

算法

步骤1:声明一个名为generatePermutation的函数,该函数接收一个元素数组作为输入。

步骤2:声明最终结果数组,其中给定数组中存在的元素的所有排列都有不同的组合。现在声明它为空数组。

步骤3:我们在步骤1中刚声明的函数实际上是一个递归函数,具有两个最佳基本情况:如果数组长度为0(现在称为空数组),则不会有它的排列;如果数组长度为1(表示数组只有一个元素),则单个元素的排列始终为单个元素,因此结果为只有一个元素的相同数组。

这两个基本情况是函数的整个工作最终结束的地方,以避免无限循环和代码歧义。

步骤4:现在继续,声明一个for循环,该循环将遍历到数组的末尾,其中每次迭代都会根据i的第一个值保存当前元素。然后,使用JavaScript方法(如slice)分离出从步骤4的第一部分中存储的当前元素的其他元素,并使用concat方法将刚刚发生的事情组合起来,从而产生数组中存在的元素的一个排列组合。

步骤5:需要对我们在步骤4中刚刚保存的特定当前元素递归地执行步骤4,方法是使用递归交换其他元素,从而生成数组中存在的元素的第二个组合。

步骤6:第二个嵌套循环导致交换元素的排列,以生成元素的不同组合,然后将其与当前元素连接起来以实现步骤5。

步骤7:这就是嵌套循环和递归将如何针对数组中的每个元素工作,以生成数组中提供的作为用户输入源的元素的不同排列的组合和排序。

示例

function generatePermutation (arr)
{
   let resultArr = [];
   if(arr.length === 0) return [];
   if(arr.length ===1) return [arr];
   
   for(let i =0 ; i<arr.length ; i++)
   {
     const currentElement = arr[i];
     
     const otherElements = arr.slice(0,i).concat(arr.slice(i+1));
     const swappedPermutation = generatePermutation(otherElements);
     
     for(let j =0 ; j < swappedPermutation.length ; j++)
     {
       const finalSwappedPermutation = 
       [currentElement].concat(swappedPermutation[j]);
       
       resultArr.push(finalSwappedPermutation);
     }
   }
   
   return resultArr;
}

const arr = [1,2,3];
const finalPermutedArray = generatePermutation(arr);
console.log(finalPermutedArray);

输出

[
  [ 1, 2, 3 ],
  [ 1, 3, 2 ],
  [ 2, 1, 3 ],
  [ 2, 3, 1 ],
  [ 3, 1, 2 ],
  [ 3, 2, 1 ]  ]

下面提到的代码是查看问题陈述时人们可以想到的直接代码,稍后您可以当然将其优化到更好的空间和时间质量,使其更有效和高质量。

在上面的代码中,我们声明了一个接收数组输入的函数。然后我们一步一步地进行,首先是剪接每次迭代的第一个元素,并将数组中存在的其他元素组合起来以形成一个新的分离数组,然后使用递归和剪接和连接JavaScript方法来生成分离数组的排列,以与我们存储的每个迭代的当前元素组合,以产生给定数组的不同排列的最终结果。

时间复杂度

在上面的算法中,我们最初使用for循环遍历数组的长度,最坏情况下导致O(n),然后使用slice方法在最佳情况下花费O(1)来分离每次迭代的每个第一个元素,以及连接方法连接剩余的元素直到长度,导致O(n),添加到O(n) + O(1) + O(n) = O(2n) = O(n),其中常数无关紧要,然后是嵌套循环来遍历剩余的元素,最坏情况下导致O(n),导致O(n^2)最坏时间复杂度。

所占空间复杂度仅为O(1)。

结论

这就是我们如何通过逻辑思考和编码上下文来解决上述问题陈述,在嵌套循环和JavaScript方法(如splice和concat)以及递归的支持下,来解决生成数组中存在的元素的不同排列的问题。

更新于:2023年8月22日

4K+ 浏览量

开启您的职业生涯

完成课程获得认证

开始
广告
© . All rights reserved.