Mysql 需要不同的数字组排列

Mysql 需要不同的数字组排列,mysql,sql,math,permutation,Mysql,Sql,Math,Permutation,我有从1到36的数字。我想做的是把所有这些数字分成三组,并计算出所有不同的组排列 每组必须包含12个数字,从1到36 每个排列中,一个数字不能出现在多个组中 这里有一个例子 Permutation 1 Group 1: 1,2,3,4,5,6,7,8,9,10,11,12 Group 2: 13,14,15,16,17,18,19,20,21,22,23,24 Group 3: 25,26,27,28,29,30,31,32,33,34,35,36 Permutation 2 Group 1:

我有从1到36的数字。我想做的是把所有这些数字分成三组,并计算出所有不同的组排列

每组必须包含12个数字,从1到36

每个排列中,一个数字不能出现在多个组中

这里有一个例子

Permutation 1
Group 1: 1,2,3,4,5,6,7,8,9,10,11,12
Group 2: 13,14,15,16,17,18,19,20,21,22,23,24
Group 3: 25,26,27,28,29,30,31,32,33,34,35,36

Permutation 2
Group 1: 1,2,3,4,5,6,7,8,9,10,11,13
Group 2: 12,14,15,16,17,18,19,20,21,22,23,24
Group 3: 25,26,27,28,29,30,31,32,33,34,35,36

Permutation 3
Group 1: 1,2,3,4,5,6,7,8,9,10,11,14
Group 2: 12,11,15,16,17,18,19,20,21,22,23,24
Group 3: 25,26,27,28,29,30,31,32,33,34,35,36

这是三个例子,我预计还会有几百万/几十亿人

接下来的分析假设了组的顺序——也就是说,如果数字是1、2、3,那么分组[{1}、{2}、{3}]与分组[{3}、{2}、{1}]是不同的(事实上,从这组数字中提取时有六个不同的分组)

在你的情况下,我们如何进行?嗯,我们必须首先选择第一组。有36种方法可以选择12种方法,或者(36!)/[(12!)(24!)]=1251677700种方法。然后我们必须选择第二组。有24种方法可以选择12种方法,或者(24!)/[(12!)(12!)]=2704156种方法。由于第二种选择已经以第一种选择为条件,我们可以通过乘以这些数字得到三种选择方式的总数;从36人中选择三组12人的方法总数为3384731762521200。如果您使用8位字节表示数字,那么存储每个列表至少需要~3个五字节(我猜是列表大小的倍,即36个字节,更像~108个五字节)。这是大量的数据,需要一些时间来生成,并且需要存储大量的磁盘空间,因此请注意这一点

要真正实现这一点并不可怕。然而,如果可能的话,我认为在SQL中实现这一点会有不必要的困难。纯SQL没有返回超过n^2个条目的操作(对于简单的交叉联接),因此获得如此大量的结果需要大量的联接。此外,由于纯SQL不能执行一般的递归,因此不能执行可变数量的联接,因此我觉得不能尽可能地对过程进行泛化

您可以使用过程语言生成分组,然后将分组写入数据库。我不知道这是否是你想要的

n = 36

group1[1...12] = []
group2[1...12] = []
group3[1...12] = []

function Choose(input[1...n], m, minIndex, group)

    if minIndex + m > n + 1 then
        return

    if m = 0 then

        if group = group1 then
            Choose(input[1...n], 12, 1, group2)

        else if group = group2 then
            group3[1...12] = input[1...12]
            print group1, group2, group3

    for i = i to n do

        group[12 - m + 1] = input[i]
        Choose(input[1 ... i - 1].input[i + 1 ... n], m - 1, i, group)
当您像
那样调用它时,选择([1…36],12,1,group1)
它所做的是用长度为12的所有可能的有序子序列填充group1。此时,m=0,group=group1,因此调用
Choose([?],12,1,group2)
(对于group1的每个可能选择,因此调用
)。这将为
group2
选择长度为12的所有剩余有序子序列,此时m=0,现在group=group2。我们现在可以安全地将
group3
分配给其余条目(在选择group1和group2之后,只有一种方法可以选择group3)

我们仅通过传播开始查看递归调用的索引(
minIdx
)来获取有序子序列。我们采用有序的子序列,以避免得到同一组12项的排列(因为在一个组中顺序并不重要)

循环中对
Choose
的每次递归调用都会传递
input
,并删除一个元素:即刚刚添加到所考虑的组中的元素

我们检查
minIndex+m>n+1
,并提前停止递归,因为在这种情况下,我们跳过了输入中的太多项,无法用12项填充当前组(同时选择要排序的子序列)


您会注意到,我已经将12/36/3组的假设硬编码到程序的逻辑中。这样做是为了简洁明了,不是因为您无法在输入大小N和要形成的组数k中对其进行参数化。为此,您需要创建一个组数组(k个组,每个组大小为N/k),然后使用N/k而不是12调用
Choose
,并使用select/switch case语句而不是if/then/else来确定是再次选择
还是打印。但这些细节可以留作练习。

置换通常应用于单个集合()。您的问题毫无意义。为了让您的问题更清楚,请给出一个简单的示例,并向我们展示您从该示例中获得的完整预期结果。还要用文字作更详细的解释。就目前而言,你的问题毫无意义。我认为你遗漏了很多关于问题陈述的信息。我还认为这更适合使用“算法”标记。先解决算法,然后再考虑如何在SQL中处理它。我想你的意思是,你想要每个可能的群的组合,例如对于2个群和数字1,2,3,组合是[[1],[2,3],[[1,2],[3],[1,2],[[1,2,3],[[1,2,3],[[1,2,3],[1,2],[1,2],[1,2],[1,3],[3],[1,2],[1,2],[1,2],[3],[1,2],[1,2],[3],[1,2],[3],[1,3],[3],[1,3],[1,3],[1],[1,3],[1,3],[1],[2],[2,3],[1],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]回避问题:是否允许使用空集,您是否在寻找唯一的组合(例如,[[3],[1,2],[1,2],[3]]两种不同的组合)在组内排序是否重要?更新了问题。非常感谢你!!