Java 在N个插槽中排列K个项目的所有可能方式
我正在寻找一个算法,以找到所有组合的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个插槽中。(允许重复) 另一个例子是:Java 在N个插槽中排列K个项目的所有可能方式,java,algorithm,combinations,Java,Algorithm,Combinations,我正在寻找一个算法,以找到所有组合的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个组合。这个问题非常适合递归解决方案 一般情况下的解决方案显然是通过取N-1的解决方案,
K值是[R,G,B]&N是5,所以我需要找到3^5=81个组合。这个问题非常适合递归解决方案 一般情况下的解决方案显然是通过取
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;
List results=new ArrayList();
结果。添加(“”;//为基本情况n=0设定种子
对于(int i=0;i
它的工作原理(我希望!)与递归方法类似——在每次迭代时,它将当前进度(即n-1
的结果)保存到previousResults
,然后依次迭代这些选项,以获得将它们预先添加到先前结果的结果
将递归解决方案通过任何自动递归传递给迭代算法,并将可读性和性能与手动创建的算法进行比较,这将是一件有趣的事情。这是留给读者的练习。我将使用以k为基数的N位计数器。 e、 g: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时,操作终止
如果您尝试过,但无法做到,请发表评论。官方术语是变体,因为订购是相关的。你的问题是以N位数为基数的K数一一对应。我同意@MarkoTopolnik。但这几乎是一个常见问题,所以我投票决定结束。可能重复的