我试图写一个函数,它做以下工作:

以一个整数数组作为参数(例如[1,2,3,4]) 创建一个包含[1,2,3,4]的所有可能排列的数组,每个排列的长度为4

下面的函数(我在网上找到的)通过接受一个字符串作为参数,并返回该字符串的所有排列来实现这一点

我不知道如何修改它,使它与整数数组一起工作,(我认为这与一些方法在字符串上的工作方式不同于在整数上的工作方式有关,但我不确定…)

let permArr = [];
let usedChars = [];

function permute(input) {
    const chars = input.split("");
    for (let i = 0; i < chars.length; i++) {
        const ch = chars.splice(i, 1);
        usedChars.push(ch);
        if (chars.length === 0) {
            permArr[permArr.length] = usedChars.join("");
        }
        permute(chars.join(""));
        chars.splice(i, 0, ch);
        usedChars.pop();
    }
    return permArr
};

注意:我希望函数返回整数数组,而不是字符串数组。

我真的需要解决方案是在JavaScript。我已经知道如何在python中做到这一点


当前回答

我使用了一个字符串而不是一个数组,似乎我的算法消耗的时间更少。我把我的算法贴在这里,我测量的时间正确吗?

console.time('process');

var result = []

function swapper(toSwap){
    let start = toSwap[0]
    let end = toSwap.slice(1)
    return end + start
}


function perm(str){
    let i = str.length
    let filling = i - 1

    let buckets = i*filling
    let tmpSwap = ''
    for(let j=0; j<filling; j++){
        if(j===0){
            result.push(str)
        }else{
          if(j === 1){
              tmpSwap = swapper(str.slice(1))
              result.push(str[0]+ tmpSwap)
              if(j === filling-1 && result.length < buckets){
                  perm(swapper(str))
              }

          }else{
              tmpSwap = swapper(tmpSwap)
              result.push(str[0]+ tmpSwap)
              if(j === filling-1 && result.length < buckets){
                  perm(swapper(str))
              }
          }
        }
    }

    if(result.length = buckets){
      return result
    }else{
      return 'something went wrong'
    }

}





console.log(perm('abcdefghijk'))

console.timeEnd('process');

其他回答

如果您注意到,代码实际上在进行任何排列之前将字符拆分为一个数组,因此只需删除连接和拆分操作

var permArr = [], 使用的字符 = []; 函数排列(输入) { var i, ch; for (i = 0; i < input.length; i++) { ch = input.splice(i, 1)[0]; usedChars.push(ch); if (input.length == 0) { permArr.push(usedChars.slice()); } 排列(输入); input.splice(i, 0, ch); usedChars.pop(); } 返回烫发 }; document.write(JSON.stringify(permute([5, 3, 7, 1])));

function swap(array1, index1, index2) {
    var temp;
    temp = array1[index1];
    array1[index1] = array1[index2];
    array1[index2] = temp;
}

function permute(a, l, r) {
    var i;
    if (l == r) {
        console.log(a.join(''));
    } else {
        for (i = l; i <= r; i++) {
            swap(a, l, i);
            permute(a, l + 1, r);
            swap(a, l, i);
        }
    }
}


permute(["A","B","C", "D"],0,3);

//示例执行 //更多细节请参考此链接

/ / http://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/

这是一个有趣的任务这是我的贡献。它非常简单和快速。如果有兴趣,请耐心阅读。

如果你想快速完成这项工作,你肯定得让自己进入动态编程。这意味着您应该忘记递归方法。那是肯定的……

好的,le_m的代码,它使用了Heap的方法,似乎是目前为止最快的。我的算法还没有名字,我不知道它是否已经实现了,但它非常简单和快速。与所有动态规划方法一样,我们将从最简单的问题开始,然后走向最终的结果。

假设我们有一个数组a =[1,2,3],我们将从它开始

r = [[1]]; // result
t = [];    // interim result

然后遵循以下三个步骤;

对于r (result)数组的每一项,我们将添加输入数组的下一项。 我们将旋转每个项的长度多次,并将每个实例存储在中间结果数组t中(好吧,除了第一个不浪费时间旋转0)。 一旦我们处理完r的所有项,中间数组t应该保存下一层的结果,因此我们使r = t;T = [];一直到输入数组a的长度。

下面是我们的步骤;

r array   | push next item to |  get length many rotations
          |  each sub array   |       of each subarray
-----------------------------------------------------------
[[1]]     |     [[1,2]]       |     [[1,2],[2,1]]
----------|-------------------|----------------------------
[[1,2],   |     [[1,2,3],     |     [[1,2,3],[2,3,1],[3,1,2],
 [2,1]]   |      [2,1,3]]     |      [2,1,3],[1,3,2],[3,2,1]]
----------|-------------------|----------------------------
previous t|                   |
-----------------------------------------------------------

这就是代码

function perm(a){ var r = [[a[0]]], t = [], s = []; if (a.length <= 1) return a; for (var i = 1, la = a.length; i < la; i++){ for (var j = 0, lr = r.length; j < lr; j++){ r[j].push(a[i]); t.push(r[j]); for(var k = 1, lrj = r[j].length; k < lrj; k++){ for (var l = 0; l < lrj; l++) s[l] = r[j][(k+l)%lrj]; t[t.length] = s; s = []; } } r = t; t = []; } return r; } var arr = [0,1,2,4,5]; console.log("The length of the permutation is:",perm(arr).length); console.time("Permutation test"); for (var z = 0; z < 2000; z++) perm(arr); console.timeEnd("Permutation test");

在多次测试中,我已经看到它在25~35ms内解决了[0,1,2,3,4]的120个排列2000次。

在精神上类似于@crl的haskell风格的解决方案,但使用reduce:

function permutations( base ) {
  if (base.length == 0) return [[]]
  return permutations( base.slice(1) ).reduce( function(acc,perm) {
    return acc.concat( base.map( function(e,pos) {
      var new_perm = perm.slice()
      new_perm.splice(pos,0,base[0])
      return new_perm
    }))
  },[])    
}

这是我做的一个…

const permute = (ar) =>
  ar.length === 1 ? ar : ar.reduce( (ac,_,i) =>
    {permute([...ar.slice(0,i),...ar.slice(i+1)]).map(v=>ac.push([].concat(ar[i],v))); return ac;},[]);

又来了,只不过写得不那么简洁了……

function permute(inputArray) {
  if (inputArray.length === 1) return inputArray;
  return inputArray.reduce( function(accumulator,_,index){
    permute([...inputArray.slice(0,index),...inputArray.slice(index+1)])
      .map(value=>accumulator.push([].concat(inputArray[index],value)));
    return accumulator;
  },[]);
}

工作原理:如果数组比一个元素长,它会遍历每个元素,并将其与对自身的递归调用连接起来,其余元素作为参数。它不会改变原始数组。