【问题标题】:all possible ways in which K items can be arranged in N slots将 K 个项目排列在 N 个插槽中的所有可能方式
【发布时间】:2012-07-06 19:20:27
【问题描述】:

我正在寻找一种算法来找到 n 个项目的 K 值的所有组合。

例子:

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 种组合。

【问题讨论】:

  • 官方术语是variations,因为顺序是相关的。您的问题与 N 位基数 K 数字一一对应。
  • 我同意@MarkoTopolnik。但这几乎是关于 SO 的常见问题解答,所以我投票结束。

标签: java algorithm combinations


【解决方案1】:

这个问题非常适合递归解决方案。

一般情况下的解决方案显然是通过采用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,然后依次迭代选项,以获取将它们添加到先前结果的结果。

看看通过任何自动递归到迭代算法传递递归解决方案的效果,并将可读性和性能与这个手工创建的算法进行比较,将会很有趣。这留给读者作为练习。

【讨论】:

    【解决方案2】:

    我将使用以 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 时,动作终止。

    如果您尝试过但不能这样做,请在评论中告诉它。

    【讨论】:

      猜你喜欢
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-02
      • 2020-07-16
      相关资源
      最近更新 更多