我试图实现的方法就像
/*
e.g. {1, 2, 3}, k = 2
--->
[ (), () ],
[ (1), () ],
[ (), (1) ],
[ (2), () ],
[ (), (2) ],
[ (3), () ],
[ (), (3) ],
[ (1), (2) ],
[ (2), (1) ],
[ (1), (3) ],
[ (3), (1) ],
[ (2), (3) ],
[ (3), (2) ],
[ (1,2), () ],
[ (2,3), () ],
[ (1,3), () ],
[ (), (1,2) ],
[ (), (1,3) ],
[ (), (2,3) ],
[ (1,2), (3) ],
[ (2,3), (1) ],
[ (1,3), (2) ],
[ (3), (1,2) ],
[ (1), (2,3) ],
[ (2), (1,3) ],
[ (1,2,3), () ],
[ (), (1,2,3,) ]
*/
public static List<List<T>> SpecialPartition<T>(this List<T> source, int k)
{
throw new NotImplementedException();
}
我首先想知道是否有一些已知的(Donald Knuth?)算法。注意桶的顺序如何重要,例如我认为(1,2), (3)
和(3), (1,2)
是单独的结果。
答案 0 :(得分:3)
请注意,每个元素都可以占用(K+1)
个地点之一(K个存储桶和任意存储桶中的一个位置)。
因此有M=(K+1)^N
个组合(此处为(2+1)^3=27 variants
),范围0..M-1
中的每个数字都对应于唯一组合(一对一映射)。
生成所有组合的简单方法是为范围0..M-1
创建循环并在(K + 1) - 数字系统中表示循环计数器
for C = 0..M-1
d = C
for i = 0..N-1
Bucket for i-th element = d %% (K+1)
d = d / (K+1)
例如,可能会映射21 10 = 210 3 :第二个存储桶中的第一个元素,第一个存储桶中的第二个元素,以及第三个元素关闭:[ (2), (1) ]
16 10 = 121 3 :[ (1,3), (2) ]