在 JavaScript 中生成数组的所有可能排列

javascriptweb developmentfront end technologyobject oriented programming

在给定的问题陈述中,我们被要求生成 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 ] ;

// 生成所有排列

[ 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 的第一个值保存当前元素。然后使用类似slice的javascript方法将步骤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 ]  ]

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

在上面的代码中,我们声明了一个接受数组输入的函数。然后我们一步一步来,首先拼接每次迭代的第一个元素,然后组合数组中存在的其他元素以形成一个新的分离数组,然后使用递归生成分离数组的排列,并使用 splice 和 concat javascript 方法与我们存储的每次迭代的当前元素相结合,以产生作为输入的特定数组的不同排列的最终结果。

时间复杂度

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

所采用的空间复杂度仅为 O(1)。

结论

这就是我们如何解决上述问题陈述,在编码上下文中逻辑思维,借助嵌套循环和 JavaScript 方法(如 splice 和 concat)与递归支柱来解决生成数组中元素的不同排列的情况。


相关文章