生成JavaScript数组的排列

时间:2016-06-01 22:46:22

标签: javascript arrays recursion permutation

我在javascript中有一个n个不同元素的数组,我知道有n个!订购这些元素的可能方式。我想知道什么是最有效(最快)的算法来生成这个数组的所有可能的排序?

我有这段代码:

var swap = function(array, frstElm, scndElm) {

    var temp = array[frstElm];
    array[frstElm] = array[scndElm];
    array[scndElm] = temp;
}

var permutation = function(array, leftIndex, size) {

    var x;

    if(leftIndex === size) {

        temp = "";

        for (var i = 0; i < array.length; i++) {
            temp += array[i] + " ";
        }

        console.log("---------------> " + temp);

    } else {

        for(x = leftIndex; x < size; x++) {
            swap(array, leftIndex, x);
            permutation(array, leftIndex + 1, size);
            swap(array, leftIndex, x);
        }
    }
}

arrCities = ["Sidney", "Melbourne", "Queenstown"];
permutation(arrCities, 0, arrCities.length);

并且它可以工作,但我想交换每个项目以获得组合是一个有点昂贵的内存明智,我认为这样做的好方法只是关注数组的索引并获得数字的所有排列,我想知道是否有办法计算所有这些而不必在阵列中切换元素?我想递归可以得到所有这些,我需要帮助才能这样做。

例如,如果我有:

arrCities = ["Sidney", "Melbourne", "Queenstown"];

我希望输出为:

[[012],[021],[102],[120],[201],[210]]

或:

[[0,1,2],
 [0,2,1],
 [1,0,2],
 [1,2,0],
 [2,0,1],
 [2,1,0]]

我正在读这个: http://en.wikipedia.org/wiki/Permutation#Algorithms_to_generate_permutations

但维基百科从未擅长解释。我不太了解它,我不得不说我的数学水平不是最好的。

4 个答案:

答案 0 :(得分:17)

此函数var a = 2; function foo(){ console.log(this.a); } (function(){ foo(); }()) function doFoo(fn){ fn(); } var obj ={ a:3, foo:foo }; doFoo(obj.foo); 返回给定数组的所有排列:

&#13;
&#13;
perm(xs)
&#13;
&#13;
&#13;

答案 1 :(得分:5)

使用Heap的方法(你可以找到你的维基百科文章链接到的in this paper),你可以生成N个元素的所有排列,其中O(N!)的运行时复杂度和O中的空间复杂度(N)。该算法基于交换元素。 AFAIK的速度和它一样快,没有更快的方法来计算所有排列。

有关实施和示例,请在相关问题at my recent answer上查看"permutations in javascript"

答案 2 :(得分:3)

这只是为了好玩-我的递归求解只需要一个字符串

const perm = a => a.length ? a.reduce((r, v, i) => [ ...r, ...perm([ ...a.slice(0, i), ...a.slice(i + 1) ]).map(x => [ v, ...x ])], []) : [[]]

答案 3 :(得分:1)

这是我基于le_m的代码的版本:

function permute(array) {
	Array.prototype.swap = function (index, otherIndex) {
		var valueAtIndex = this[index]

		this[index] = this[otherIndex]
		this[otherIndex] = valueAtIndex
	}

	var result = [array.slice()]

	, length = array.length

	for (var i = 1, heap = new Array(length).fill(0)
		; i < length
	;)
		if (heap[i] < i) {
			array.swap(i, i % 2 && heap[i])
			result.push(array.slice())
			heap[i]++
			i = 1
		} else {
			heap[i] = 0
			i++
		}

	return result
}

console.log(permute([1, 2, 3]))

这是我对相同算法的递归JavaScript实现:

Array.prototype.swap = function (index, otherIndex) {
	var valueAtIndex = this[index]

	this[index] = this[otherIndex]
	this[otherIndex] = valueAtIndex
}

Array.prototype.permutation = function permutation(array, n) {
	array = array || this
	n = n || array.length

	var result = []

	if (n == 1)
		result = [array.slice()]
	else {
		const nextN = n - 1

		for (var i = 0; i < nextN; i++) {
			result.push(...permutation(array, nextN))
			array.swap(Number(!(n % 2)) && i, nextN)
		}

		result.push(...permutation(array, nextN))
	}

	return result
}

console.log([1, 2, 3].permutation())