这是一个非常经典的问题,我发现的大多数解决方案都使用递归方法,如this。由于存在Cn,k组合,我想知道是否存在可以在O(n * Cn,k)时间内打印所有组合的算法。我认为链接中给出的答案比这要花费更多时间。此外,是否有一种算法可以打印结果而不使用额外的空间(我的意思是,没有额外的空间依赖于n和k.O(1)肯定没问题)?
感谢。
答案 0 :(得分:1)
链接的算法尽可能快地为您提供所有排列 - O(n!/k!)
- 这很慢,因为存在指数级的排列。
要在O(Cn,k)
时间内获得所有组合,您可以在其他问题的答案中使用其中一种算法:Algorithm to return all combinations of k elements from n。
答案 1 :(得分:1)
只需从Windows命令行(cscript test.js
)测试一个简单的javascript代码。
这只是带进位的总和,其中“数字”是集合中元素的位置。
没有递归,只需要存储set元素和数组来保存当前子集。
// define the initial set
var set = 'abcdefg'.split('');
var setLength = set.length;
// define the subset length and initialize the first subset
var subsetLength = 5;
var aSubset = new Array(subsetLength+1);
var i;
for( i = 0 ; i < subsetLength ; i++ ) aSubset[i]=i;
// place a guard at the end
aSubset[subsetLength] = setLength;
// generate each of the posible subsets
// This is just a sum with carry where the value of each of the "digits"
// is in the range [i..subset[i+1])
var r = 0, start = 0;
do {
// print the subset
for( i = 0 ; i < subsetLength ; i++ ) {
WScript.StdOut.Write( set[aSubset[i]] );
};
WScript.StdOut.WriteLine('');
// calculate the next subset
for( i = start, r = 1 ; i < subsetLength ; i++ ) {
aSubset[i]++;
if (aSubset[i] < aSubset[i+1]) {
start = ( i==0 ? 0 : i-1 );
r = 0;
break;
} else {
aSubset[i] = i
};
};
} while (r == 0);