这是一个有趣的任务这是我的贡献。它非常简单和快速。如果有兴趣,请耐心阅读。
如果你想快速完成这项工作,你肯定得让自己进入动态编程。这意味着您应该忘记递归方法。那是肯定的……
好的,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次。