Java 将一个组组合成多个组而不重复

Java 将一个组组合成多个组而不重复,java,kotlin,unique,combinations,Java,Kotlin,Unique,Combinations,我们有一个元素列表,[a、B、C、D、E]和三个组要组合这些元素,我想打印一个所有独特组合的列表,不重复这三个组。只有长度为[2,2,1]的组是有效的(之后可以对其进行过滤,这不是必须的,但这将是非常有效的,如果需要,可以手动将组的长度指定为参数)。我的意思是“独一无二,不重复”: [[A,B],[C,D],[E]]和[[C,D],[A,B],[E]]和[[B,A],[C,D],[E]]是相同的,所以一个组内元素的顺序或组的顺序都不重要,我对这些组合不感兴趣 在我的特殊情况下,我有16个项目和3

我们有一个元素列表,[a、B、C、D、E]三个组要组合这些元素,我想打印一个所有独特组合的列表,不重复这三个组。只有长度为[2,2,1]的组是有效的(之后可以对其进行过滤,这不是必须的,但这将是非常有效的,如果需要,可以手动将组的长度指定为参数)。我的意思是“独一无二,不重复”:

[[A,B],[C,D],[E]]和[[C,D],[A,B],[E]]和[[B,A],[C,D],[E]]是相同的,所以一个组内元素的顺序或组的顺序都不重要,我对这些组合不感兴趣

在我的特殊情况下,我有16个项目和3组,每组5、5和6个项目

我想要实现的一个例子:

/**
 * Returns all the unique combinations of a group into multiple groups
 * [data] the group of elements to combine
 * [numberOfGroups] the number of groups
 */
fun combinations(data: List<String>, numberOfGroups: Int): List<List<List<String>>> {
    // The combinations code
}

val data = listOf("A", "B", "C", "D", "E")
print(combinations(data, 3))

提前感谢您。

我不知道您的问题的一般答案,但我将尝试解决将5个元素的列表拆分为组[2,2,1]的特殊情况,并分享一些原则,这些原则可以帮助您设计更通用的解决方案

首先,让我们讨论如何表示结果。如果组内元素的顺序不重要,则可以方便地用
集合表示组,这样
集合(“a”,“B”)
等于
集合(“B”,“a”)
。然后,如果组本身在组合中的顺序无关紧要,则该组合可以是一组组,即
set

现在谈谈算法本身。将这种算法构造为递归搜索很方便:从数据中选择第一组项,然后解决没有选择项的数据的问题,并将第一组与除此之外的所有解决方案组合在一起。因此,搜索组合的函数可以如下所示:

fun combinationSequence(data: List<String>): Sequence<Set<Set<String>>> = sequence {
    for (group in possibleFirstGroups(data)) {
        val remaining = data - group
        if (remaining.isEmpty()) {
            yield(setOf(group))
        } else {
            yieldAll(combinationSequence(remaining).map { r -> setOf(group) + r })
        }
    }
}
请注意,此解决方案的复杂性随着项目的数量呈指数增长,因此我不希望16个元素的解决方案能够及时终止:)


一种降低复杂性的方法是修剪搜索空间。例如,如果我们已经找到了从<> > [a,b] < /c>组开始的所有组合,我们可以避免在中间的某个地方包含该组的组合,如<代码> [c,d],[a,b], > /p>到目前为止你尝试了什么?你被困在哪里了?@Nikolas首先我试着自己想出解决方案,要么太复杂,要么我不够聪明(而且我没有数学背景)。我发现了n!/(r!(n−r) !)组合的公式,但我认为它不适用于这里,我尝试了Guava库中的Sets.powerSet(Sets.newHashSet(myItemsList))。我也花了几个小时寻找例子,但没有一个是适用的。
fun combinationSequence(data: List<String>): Sequence<Set<Set<String>>> = sequence {
    for (group in possibleFirstGroups(data)) {
        val remaining = data - group
        if (remaining.isEmpty()) {
            yield(setOf(group))
        } else {
            yieldAll(combinationSequence(remaining).map { r -> setOf(group) + r })
        }
    }
}
fun possibleFirstGroups(data: List<String>): Sequence<Set<String>> =
        when (data.size) {
            0 -> emptySequence()
            1, 2 -> sequenceOf(data.toSet())
            else -> sequence {
                for (e1 in data) {
                    for (e2 in data - e1) {
                        yield(setOf(e1, e2))
                    }
                }
            }
        }
combinationSequence(data).distinct().forEach { println(it) }