将一个字符串列表随机分组

时间:2012-09-16 10:17:04

标签: c# algorithm

鉴于n项的字符串列表,我希望将其分为b个小组(b<=n),其中每个小组都有i to j (j>=i)个项目

一个例子: 说

List<string> lst=new List<string>(new string[]{"a","b","c","d"}); 

(因此n=4

假设提供此功能的功能是

List<List<string>> DivideIntoGroup(List<string> lst, b, i, j)

DivideIntoGroup(lst, 3, 1, 2)的可能结果之一是

{"a"},
{"b","c"},
{"d"}

我应该如何编写DivideIntoGroup函数?

2 个答案:

答案 0 :(得分:4)

我不是C#专家,所以我会给你一个纯粹的数学解决方案,希望你能用你的语言翻译它。

基本上你的任务由两个独立的部分组成:选择b组i到j元素,以及随机性。第二个应该很简单 - 只需随机随机洗牌,然后进行分组。让我们来看看有趣的部分:

如何将b组中包含ij个元素的n个元素分开? 一个直接的解决方案是在ij之间取一个随机数作为第一组元素的数量,然后是第二组等等。但是,不能保证,这样做你会不得留下元素编号不在ij之间的最后一组。此类解决方案也不是纯随机分布。

正确的方法是获取第一组元素的数量,尊重在采用尽可能多的元素时解决整个组拆分的概率 - 您基本上感兴趣的是{{1如果我们假设我们在第一组中采用task(n, b, i, j)元素,那么task(n-k, b-1, i, j)将存在多少。如果我们只能计算解的数量,你可以用它各自的概率取每个k,然后对第一组进行k的随机抽样,然后对第二组进行随机抽样,依此类推......

现在问题是:k有多少解决方案? 注意task(n, b, i, j)您可以使用递归轻松找到这些数字这一事实(使用动态优化,这样您就不必多次计算这些值)。

PS:对于解决方案的数量可能存在封闭形式的解决方案,但我无法立即弄清楚并且只要task(n, b, i, j) = sum(k=i to j) task(n-k, b - 1, i, j)保持相对较小(<10 ^ 6)的递归解决方案应该工作。

修改
PS2:实际上n * b中的数字可能非常快,所以考虑使用大整数。

答案 1 :(得分:0)

作为解决方案我会做什么,这当然是伪代码:

func( n, b, i, j )
{
    if(n == 0)
        return //finished
    if(i>j or i>min(j,n))
        return //no solution possible down this path
    out = choose_random_between (i , min(j,n)) 
    current_ave_of_cells_per_group = ( (n - out) / (b - 1) )
    if current_ave_of_cells_per_group < i
        func ( n, b, i, min(out-1,n) )
    else if current_ave_of_cells_per_group > j
        func ( n, b, out+1, min(j,n) )
    else    
        **form the group consisting of 'out' numbers**
        func ( n-out, b-1, i, min(j,n-out) )
}