【问题标题】:All combinations of dividing an integer into several "groups" [duplicate]将整数分成几个“组”的所有组合[重复]
【发布时间】:2018-04-12 22:10:39
【问题描述】:

假设我= 有 5 个糖果,我想找到所有可能的组合,以便在我的 3 个孩子之间分享它们。

这将类似于以下内容:

5 for kid_A, 0 for kid_B, 0 for kid_3
0 for kid_A, 5 for kid_B, 0 for kid_3
....
4 for kid_A, 1 for kid_B, 0 for kid_3
4 for kid_A, 0 for kid_B, 1 for kid_3
....
and so on 

有没有找到这种组合的算法?

到目前为止,我已经设法计算出前 3 个组合,我把所有的糖果都给了我的一个孩子,剩下的得到 0;但是一旦我完成了第一次迭代,我就迷失了如何划分。

【问题讨论】:

  • 可以参考以下链接stackoverflow.com/questions/6772521/…
  • 这可以很容易地递归完成。您可以给第一个孩子任意数量的糖果,然后递归地应用算法在剩余的孩子之间分配剩余的糖果。
  • @arjunsv3691 您提供的链接不适用于此问题。
  • @rici 所以我明白了;谢谢。它一个重复,但不是那个链接。这个问题已经在 Python 和 C 中的 SO 上解决了,也许还有 Java;我看的不够仔细。
  • 欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。

标签: java algorithm computation


【解决方案1】:

这个问题有三个方面:

  • 我可以给一个孩子最多 N 个糖果有多少种方法? (每个孩子的排列)
  • 对于其中的每一个,我可以用多少种方式给另一个孩子剩下的 N 个糖果? (递归,也许)
  • 什么时候停止分配糖果? (终止)

你可以给一个孩子 n 个糖果有多少种方法很简单:对于 0 -> n 中的每一个,你得到一个排列,例如第一个孩子可以得到 0、1、2、3、4 或 5 个糖果。

对于第二个孩子,您可以在减去第一个孩子的糖果数量后重复此操作。因此,对于 0 -> m,其中 m = 5 - n。

对于 n 和 m 的这些排列中的每一个,第三个孩子只需得到余数:t = 5 - (n + m)。

由此,您可以制定两个循环来生成排列。对于任何数量的孩子或糖果,有一个更一般的情况,但你必须小心你的递归(堆栈大小问题),并意识到对于大量的组合可能是巨大的。

【讨论】:

    【解决方案2】:

    代码

    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
    
    public class Example {
        public static void main(final String... args) {
            for (final List<Integer> option : divide(5, 3)) {
                System.out.printf("%d for kid_A, %d for kid_B, %d for kid_3%n", option.toArray());
            }
        }
    
        private static List<List<Integer>> divide(final int count, final int groups) {
            if (groups == 1) {
                final List<Integer> inner = new ArrayList<>(1);
                inner.add(count);
                final List<List<Integer>> outer = new ArrayList<>(1);
                outer.add(inner);
                return outer;
            }
            return IntStream.range(0, count + 1)
                .mapToObj(Integer::valueOf)
                .flatMap(p -> {
                    return divide(count - p, groups - 1).stream()
                        .map(q -> {
                            q.add(p);
                            return q;
                        });
                }).collect(Collectors.toList());
        }
    }
    

    工作原理

    首先假设如果你有 1 个孩子,你就给他们所有的糖果。

    如果您有多个孩子,则计算出给第一个孩子多少个,然后递归找出其他孩子可以有多少个。

    flatMap 获取所有选项并添加当前孩子获得的糖果数量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-19
      • 2015-04-28
      相关资源
      最近更新 更多