C# 将字符串列表随机分组
给定一个C# 将字符串列表随机分组,c#,algorithm,C#,Algorithm,给定一个n项的字符串列表,我希望将其划分为b组(b=I)项 例如: 说 划分为组(lst,3,1,2)的一个可能结果是 {"a"}, {"b","c"}, {"d"} 我应该如何编写dividentogroup函数?我不是C#专家,所以我会给你一个纯数学的解决方案,希望你能用你的语言翻译它 基本上,您的任务由两个独立的部分组成:选择b组,每组i到j个元素,以及随机性。第二种方法应该很简单——首先随机洗牌元素,然后进行分组。让我们进入有趣的部分: 如何将包含i的b组中的n个元素拆分为j组? 一个
n
项的字符串列表,我希望将其划分为b
组(b=I)
项
例如:
说
划分为组(lst,3,1,2)
的一个可能结果是
{"a"},
{"b","c"},
{"d"}
我应该如何编写dividentogroup函数?我不是C#专家,所以我会给你一个纯数学的解决方案,希望你能用你的语言翻译它
基本上,您的任务由两个独立的部分组成:选择b组,每组i到j个元素,以及随机性。第二种方法应该很简单——首先随机洗牌元素,然后进行分组。让我们进入有趣的部分:
如何将包含i
的b
组中的n个元素拆分为j
组?
一个直接的解决方案是在i
和j
之间随机选取第一组元素的数量,然后是第二组元素的数量。但是,不能保证这样做不会让最后一组元素的数量不在i
和j
之间。这样的解决方案也不是做纯随机分布
正确的方法是获得第一组的元素数量,考虑到当你取尽可能多的元素时整体组分裂的解的概率-你基本上感兴趣的是任务(n,b,i,j)
的总体解有多少,以及任务(n-k,b-1,i,j)的总体解有多少
如果我们假设在第一组中取k
元素。如果我们能够计算出解的个数,你可以取每个k及其各自的概率,对第一组k进行随机抽样,然后对第二组k进行随机抽样,依此类推
所以现在的问题是:任务(n,b,i,j)
有多少种解决方案?
注意到task(n,b,i,j)=sum(k=i到j)task(n-k,b-1,i,j)
使用递归可以很容易地找到这些数字(使用动态优化,因此无需多次计算值)
PS:对于解决方案的数量,可能有一个封闭形式的解决方案,但我不能马上计算出来,只要n*b
保持相对较小(<10^6),递归解决方案应该可以工作
编辑PS2:实际上,在<代码>任务(n,b,i,j)< /代码>中的数字可能非常大,所以考虑使用大整数。 我将做为一个解决方案是这样的,这当然是伪代码:
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) )
}
func(n,b,i,j)
{
如果(n==0)
返回//已完成
如果(i>j或i>min(j,n))
return//此路径下没有可能的解决方案
out=在(i,min(j,n))之间选择随机
每组单元的当前平均值=((n-out)/(b-1))
如果每组的电池的当前值j
func(n,b,out+1,min(j,n))
其他的
**组成由“out”数字组成的组**
func(n-out,b-1,i,min(j,n-out))
}
如果b>=n
,没有太多的方法将元素分成b
组:)你的意思是b错了:List lst=new List(新字符串[]{“a”、“b”、“c”、“d”})代码>似乎是一个家庭作业问题。对列表进行排序并将其分组?@dasblinkenlight是的,你是对的,我编辑了问题。我认为这不是均匀随机的。它是均匀随机的,因为每次随机选择数字,如果某个阶段的数字不可能,它将尝试选择一个不同的数字,该数字现在被限定为一个较小的边界,以适应更多的约束,其他数字,现在不可能被选择是数字,不能被选择,以适应这个解决方案,无论什么,这样就不会伤害随机性。这样做,直到无论他选择什么数字,约束都不会通过。。或更可能,直到他完成他的所有数字成组,并且没有更多的数字证明是不正确的:考虑一个情况下,i=1,j=7,n=43,b=7。您将选择概率为1/7的大小为1的第一组,而462个解决方案中只有1个是从第一组1开始的。好吧,但您不明白的是,这不是唯一的一条路径,因为递归如果失败会返回,因此,如果我选择第一组7号,并继续选择7号,最终将失败,因此将有另一个机会从1-6号中选择一组。此外,你说了462个解决方案,但没有提到全部解决方案。正如你所看到的,因为它是递归的,所以给出一个概率来选择第一个概率,并把它作为总概率是不正确的。而且现在我想起来了,我没有看到他说任何关于使它均匀随机的事情。。
{"a"},
{"b","c"},
{"d"}
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) )
}