将整数分成几个“组”的所有组合

时间:2017-10-31 16:49:16

标签: java algorithm computation

假设我=有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 

是否有算法可以找到这种组合?

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

2 个答案:

答案 0 :(得分:0)

这个问题有三个方面:

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

给孩子喂糖果的方法很简单:你可以为每个孩子获得一个排列 - >> n,例如第一个孩子可以给0,1,2,3,4或5个糖果。

对于第二个孩子,一旦减去第一个孩子的甜食数量,就可以重复这个。所以,对于0 - > m,其中m = 5 - n。

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

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

答案 1 :(得分:0)

代码

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());
    }
}

工作原理

这开始于基本的假设,如果你有一个孩子,你给他们所有的糖果。

如果你有一个以上的孩子,可以计算出给第一个孩子多少,然后通过递归来找出其他人可以有多少孩子。

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