组合学:构建 10 组,每组 100 个元素,同时元素保持排序
我有一个关于组合学的问题。不幸的是,我无法抽象地描述它,所以我尝试用一个故事来解释它。 :)
问题:
- 校园里有 100 个孩子。
- 它们都有独特的高度,假设值为 100-199 厘米。
- 您想要建立 10 个小组,每个小组由 1-99 名儿童组成。
- 当孩子们必须按身高排序时,如何才能建立所有的小组呢?
- 我需要为这些群体提供所有可能的解决方案,因为找到一个星座并不难。
简短易懂:
所有 100 个孩子并排站立。您只需决定在哪里将它们分组并找到所有解决方案。
示例(值为高度):
[120 ... 190 ... 199] ... [126 ... 137 ... 144 ... 188] 不可能
[101] ... [104 ... 105 ... 112 ... 149] ... [169 ... 189] 有可能
我希望你能帮助我。预先非常感谢您!
PS:这不是家庭作业。 ;)通常,我需要一个用数字来完成此操作的函数。但我无法像“在所有数字都已排序的情况下构建 k 组数字”一样抽象地描述这一点。我以为这样你就不会明白。 :) PHP 的解决方案是最好的,但我也很高兴看到其他语言的解决方案。 :)
I've got a problem concerning combinatorics. Unfortunately, I can't describe it abstractly so I try to explain it as a story. :)
Problem:
- There are 100 children on the schoolyard.
- They all have unique heights, assuming the values are 100-199cm.
- You want to build 10 groups, each consisting of 1-99 children.
- How can you build all the groups while the children must be sorted by their height?
- I need all possible solutions for these groups since it isn't hard to find one constellation.
Short and easy:
All 100 children stand side by side. You only have to decide where to split them into groups and find all solutions for this.
Example (values are the heights):
[120 ... 190 ... 199] ... [126 ... 137 ... 144 ... 188] is not possible
[101] ... [104 ... 105 ... 112 ... 149] ... [169 ... 189] is possible
I hope you can help me. Thank you very much in advance!
PS: It's no homework. ;) Normally, I need a function which does this with numbers. But I couldn't describe this abstractly like "building k groups of numbers while all numbers are sorted". I thought you wouldn't understand it this way. :) A solution in PHP would be best but I would be glad to see solutions in other languages as well. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我了解,您实际上是在寻求将区间 [100,199] 划分为 10 个部分的方法,即您想要找到数字 x[0], ..., x[10] ,这样:
定义一个递归函数
partition(intervalSize,pieces)
计算给定间隔的分区方式数量。您正在执行partition(100, 10)
。下面的 Java 代码计算分区数(抱歉,我不太了解 PHP):
下面的 Java 代码打印出实际的分区。由于 (100,10) 的分区数量非常高,因此我将说明 (5,3) 的答案:
输出为:
As I understand it, you are effectively asking for ways of partitioning the interval [100,199] into 10 parts, i.e. you want to find numbers x[0], ..., x[10] such that:
Define a recursive function
partition(intervalSize, pieces)
which counts the number of ways to partition a given interval. You are afterpartition(100, 10)
.The following Java code counts the partitions (sorry, don't know PHP that well):
The following Java code prints out the actual partitions. Because the number of partitions is so high for (100,10), I'm illustrating the answer for (5,3):
The output is:
一般情况下,有100个!排列 100 个项目的方法,但由于您保留了顺序,因此可以大大减少问题的规模。您所描述的是整数分区问题。例如,假设您将数字 5 划分为所有可能的整数子集,总和为 5,您将得到集合 {5}, {4, 1}, {3, 2}, {3, 1, 1 ,}, {2, 2, 1}, {2, 1, 1, 1}, {1, 1, 1, 1, 1}。
整数分区的数量随着整数的大小呈指数增长,但指数增长足够慢,您可以枚举 n = 100 的所有分区,因为它们只有 190,569,292 个。这里的附加约束是您想要过滤所有分区以查找恰好包含 10 个项目的集合,这可以通过使用 Ferrer 图轻松枚举。
我可以通过将数字 20 划分为 3 个桶来演示费雷尔图:从 20 列 x 3 行网格开始,如下所示:
因此,第一个分区是 {18, 1, 1}
现在从堆栈顶部移动一个项目进入下一个槽:
我们的新分区是 {17, 2, 1}。我们可以将另一项从一个堆栈移到另一个堆栈:
现在我们有 {16, 3, 1}。继续以这种方式,直到枚举完所有排列(由您决定 {17, 1, 2} 是否是与 {17, 2, 1} 不同的分区)。
从这一点来看,您应该能够想象出您需要的算法的总体轮廓——也就是说,如果您愿意接受从头开始编写这个函数的挑战。其他人已经编写了很多高效的函数来解决这个问题容易地。
Normally, there 100! ways to permute 100 items, but since you're preserving order, you can reduce your problem size down substantially. What you're describing is an integer partitioning problem. For example, let's say you were partitioning the number 5 into all possible integer subsets which add up to 5, you'd get the sets {5}, {4, 1}, {3, 2}, {3, 1, 1,}, {2, 2, 1}, {2, 1, 1, 1}, {1, 1, 1, 1, 1}.
The number of integer partitions grows exponentially with the size of the integer, but the exponential growth is slow enough that you can enumerate through all partitions of n = 100, since there are only 190,569,292 of them. The additional constraint here is that you want to filter all of your partitions for sets containing exactly 10 items, which is easy to enumerate through using a Ferrer diagram.
I can demonstrate a Ferrer diagram by partition the number 20 into 3 buckets: start with a 20 col x 3 row grid as follows:
So, the first partition is {18, 1, 1}
Now move an item from the top of the stack into the next slot:
Our new partition is {17, 2, 1}. We can another item from one stack to the other:
Now we have {16, 3, 1}. You continue in this fashion until you've enumerate all permutations (its up to you whether {17, 1, 2} is a distinct partition from {17, 2, 1}).
From this point, you should be able to envision the general outline of the algorithm you need -- that is, if you'd like the challenge of writing this function from scratch. Other people have already written lots of efficient functions to solve the problem easily.