JavaScript - 生成数组的所有排列

时间:2016-11-17 12:27:52

标签: javascript arrays permutation

我有不同的数组,都有数字,但元素数量不同:

var ar1 = [2, 5];
var ar2 = [1, 2, 3];

我需要获得每个数组的所有排列。输出元素的长度应始终与输入数组相同。

这个结果应该是一个数组数组,如下所示:

表示ar1:

[2, 5]
[5, 2]

表示ar2:

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

我不想要笛卡尔积,每个阵列都应该自行处理。

到目前为止我找到的所有解决方案都只创建了与顺序无关的数组,因此ar1的结果只有一个数组,而不是两个。

解决方案应该适用于输入数组中的任意数量的元素。我们可以假设输入数组中没有重复的值。

2 个答案:

答案 0 :(得分:4)

您可以使用permutation迭代和递归方法,直到没有更多的元素要进行ditribute。



function permutation(array) {
    function p(array, temp) {
        var i, x;
        if (!array.length) {
            result.push(temp);
        }
        for (i = 0; i < array.length; i++) {
            x = array.splice(i, 1)[0];
            p(array, temp.concat(x));
            array.splice(i, 0, x);
        }
    }

    var result = [];
    p(array, []);
    return result;
}

console.log('something bigger [1,2,3,4,5,6,7]');
console.time('t1');
permutation([1, 2, 3, 4, 5, 6, 7]);
console.timeEnd('t1');

console.log(permutation([2, 5]));
console.log(permutation([1, 2, 3]));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 1 :(得分:2)

不确定这是否是最佳方式,但似乎有效。

@Nina的解决方案看起来很不错,但它确实有点阵列连接&amp;切片,所以这对于较大的集合可能更好,因为它避免了这种情况。我确实使用一个对象进行重复检查,但是在JS中,哈希映射速度非常快。

好奇,性能测试也是如此。 做[1,2,3,4,5,6,7],使用@Nina的解决方案需要38.8秒。 做我的toke 175ms ..所以数组concat / slice是一个巨大的性能命中,标记的重复将有相同的问题。只是需要注意的事情。

&#13;
&#13;
var ar1 = [2, 5];
var ar2 = [1, 2, 3];

function combo(c) {
  var r = [],
      len = c.length;
      tmp = [];
  function nodup() {
    var got = {};
    for (var l = 0; l < tmp.length; l++) {
      if (got[tmp[l]]) return false;
      got[tmp[l]] = true;
    }
    return true;
  }
  function iter(col,done) {    
    var l, rr;
    if (col === len) {      
      if (nodup()) {
        rr = [];
        for (l = 0; l < tmp.length; l++) 
          rr.push(c[tmp[l]]);        
        r.push(rr);
      }
    } else {
      for (l = 0; l < len; l ++) {            
        tmp[col] = l;
        iter(col +1);
      }
    }
  }
  iter(0);
  return r;
}

console.log(JSON.stringify(combo(ar1)));
console.log(JSON.stringify(combo(ar2)));
console.log('something bigger [1,2,3,4,5,6,7]');
console.time('t1');
combo([1,2,3,4,5,6,7]);
console.timeEnd('t1');
&#13;
&#13;
&#13;