当前位置:首页 > JavaScript

js数组实现全排列

2026-04-04 20:38:08JavaScript

使用递归方法实现全排列

递归方法是实现全排列的经典方式,通过不断交换数组元素的位置来生成所有可能的排列组合。

function permute(nums) {
  const result = [];

  function backtrack(start) {
    if (start === nums.length - 1) {
      result.push([...nums]);
      return;
    }

    for (let i = start; i < nums.length; i++) {
      [nums[start], nums[i]] = [nums[i], nums[start]];
      backtrack(start + 1);
      [nums[start], nums[i]] = [nums[i], nums[start]];
    }
  }

  backtrack(0);
  return result;
}

// 示例用法
console.log(permute([1, 2, 3]));

使用堆算法实现全排列

堆算法是一种非递归的全排列生成方法,效率较高且不需要额外空间。

js数组实现全排列

function heapPermutation(nums) {
  const result = [];
  const n = nums.length;

  function generate(k) {
    if (k === 1) {
      result.push([...nums]);
      return;
    }

    generate(k - 1);

    for (let i = 0; i < k - 1; i++) {
      if (k % 2 === 0) {
        [nums[i], nums[k - 1]] = [nums[k - 1], nums[i]];
      } else {
        [nums[0], nums[k - 1]] = [nums[k - 1], nums[0]];
      }
      generate(k - 1);
    }
  }

  generate(n);
  return result;
}

// 示例用法
console.log(heapPermutation([1, 2, 3]));

使用库函数简化实现

现代JavaScript提供了更简洁的实现方式,可以结合扩展运算符和reduce方法。

js数组实现全排列

function permutations(arr) {
  return arr.reduce((acc, val) => 
    acc.flatMap(perm => 
      [...Array(perm.length + 1)].map((_, i) => 
        [...perm.slice(0, i), val, ...perm.slice(i)]
      )
    ), [[]]
  ).filter(perm => perm.length === arr.length);
}

// 示例用法
console.log(permutations([1, 2, 3]));

处理包含重复元素的情况

当数组中存在重复元素时,需要额外处理以避免生成重复的排列。

function permuteUnique(nums) {
  const result = [];
  nums.sort((a, b) => a - b);

  function backtrack(temp, used) {
    if (temp.length === nums.length) {
      result.push([...temp]);
      return;
    }

    for (let i = 0; i < nums.length; i++) {
      if (used[i] || (i > 0 && nums[i] === nums[i - 1] && !used[i - 1])) continue;
      used[i] = true;
      temp.push(nums[i]);
      backtrack(temp, used);
      used[i] = false;
      temp.pop();
    }
  }

  backtrack([], Array(nums.length).fill(false));
  return result;
}

// 示例用法
console.log(permuteUnique([1, 1, 2]));

性能优化建议

对于大型数组,全排列的计算量会急剧增加。可以考虑使用生成器函数来按需产生排列,而不是一次性生成所有结果。

function* permuteGenerator(arr) {
  if (arr.length <= 1) yield arr;
  else {
    const [first, ...rest] = arr;
    for (const perm of permuteGenerator(rest)) {
      for (let i = 0; i <= perm.length; i++) {
        yield [...perm.slice(0, i), first, ...perm.slice(i)];
      }
    }
  }
}

// 示例用法
for (const perm of permuteGenerator([1, 2, 3])) {
  console.log(perm);
}

这些方法涵盖了从基础到进阶的多种实现方式,可以根据具体需求选择最适合的方案。递归方法直观易懂,堆算法效率较高,而生成器函数适合处理大规模数据。对于包含重复元素的数组,需要特别注意去重处理。

标签: 数组排列
分享给朋友:

相关文章

vue 实现数组排序

vue 实现数组排序

在 Vue 中实现数组排序的方法 使用 JavaScript 原生排序方法 Vue 中可以直接调用 JavaScript 的 Array.prototype.sort() 方法对数组进行排序。对于数字…

vue实现数组绑定

vue实现数组绑定

Vue 数组绑定的实现方法 Vue 提供了多种方式实现数组的响应式绑定,确保数据变化时视图自动更新。以下是常见的实现方法: 使用 v-for 指令渲染数组 通过 v-for 指令可以遍历数组并渲染…

实现vue数组双向绑定

实现vue数组双向绑定

Vue 数组双向绑定的实现方法 Vue 通过数据劫持和发布-订阅模式实现数据的双向绑定,但直接修改数组的某些方法(如索引赋值)无法触发视图更新。以下是实现数组双向绑定的几种方法: 使用 Vue.se…

vue实现数组元素绑定

vue实现数组元素绑定

Vue 数组元素绑定方法 在 Vue 中实现数组元素绑定需要特别注意响应式更新的问题。以下是几种常见实现方式: 直接索引绑定(不推荐) 直接通过索引修改数组元素不会触发视图更新: this.arr…

原生加数组实现vue

原生加数组实现vue

使用原生 JavaScript 和数组实现 Vue 的核心功能 Vue 的核心功能包括数据响应式、模板渲染和指令绑定。通过原生 JavaScript 和数组可以模拟部分功能,以下是一个简化版的实现方式…

react如何遍历数组

react如何遍历数组

遍历数组的方法 在React中遍历数组并渲染元素,可以使用多种方法。以下是常见的几种方式: 使用map方法 map是React中最常用的数组遍历方法,它会返回一个新的数组,适合渲染列表。…