我正在寻找一种算法来查找K值与n项的所有组合。
示例:
K值是[R,B]& N是2所以我得到{RR,RB,BR,BB} 2 * 2 = 4种方式
K值是[R,B]& N是3所以我得到{RRR,RRB,RBB,RBR,BRR,BRB,BBR,BBB} 2 * 2 * 2 = 8种方式
我需要找出通用算法来找到K个项目可以在N个槽中排列的所有可能方式。 (允许重复)
另一个例子是:
K值是[R,G,B]& N是5所以我需要找到3 ^ 5 = 81种组合。
答案 0 :(得分:2)
这个问题非常适合递归解决方案。
通常情况下的解决方案是通过采用N - 1
的解决方案,然后将每个集合的元素依次添加到结果中来形成的。在伪代码中:
f(options, 0) = []
f(options, n) = options foreach o => o ++ f(options, n-1)
这可以在Java中递归实现,但是对于中等大小的n
值,你会遇到堆栈溢出错误;我还怀疑JIT编译器在优化递归算法方面效率较低,因此性能会受到影响。
但是,递归算法总是可以转换为循环等价物。在这种情况下,它可能看起来像:
List<String> results = new ArrayList<String>();
results.add(""); // Seed it for the base case n=0
for (int i = 0; i < n; i ++) {
List<String> previousResults = results;
results = new ArrayList<String>();
for (String s : options) {
for (String base : previousResults) {
results.add(s + base);
}
}
}
return results;
这与(我希望!)类似于递归方法 - 在每次迭代时它将当前进度(即n-1
的结果)“保存”到previousResults
,然后迭代选项反过来,得到的结果是将它们添加到之前的结果中。
通过任何自动递归到迭代算法传递递归解决方案的效果会很有趣,并将可读性和性能与这个手工创建的算法进行比较。这留给读者练习。
答案 1 :(得分:1)
我将在基数k中使用N位的计数器。 例如:k = 3,n = 5
(0,0,0,0,0)
(0,0,0,0,1),
....
(2,2,2,2,2)
实现这样的计数器很简单,只需保持大小为n + 1的数组,首先将所有元素设置为零,每次增加最新元素,如果它将超过k-1,则增加下一个邻居(直到邻居超过K-1)。当n + 1个元素设置为1时,动作终止。
如果您尝试过但不能这样做,请通过评论告诉它。