鉴于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函数?
答案 0 :(得分:4)
我不是C#专家,所以我会给你一个纯粹的数学解决方案,希望你能用你的语言翻译它。
基本上你的任务由两个独立的部分组成:选择b组i到j元素,以及随机性。第二个应该很简单 - 只需随机随机洗牌,然后进行分组。让我们来看看有趣的部分:
如何将b
组中包含i
到j
个元素的n个元素分开?
一个直接的解决方案是在i
和j
之间取一个随机数作为第一组元素的数量,然后是第二组等等。但是,不能保证,这样做你会不得留下元素编号不在i
和j
之间的最后一组。此类解决方案也不是纯随机分布。
正确的方法是获取第一组元素的数量,尊重在采用尽可能多的元素时解决整个组拆分的概率 - 您基本上感兴趣的是{{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) )
}