簡體   English   中英

將一個字符串列表隨機分組

[英]Divide a list of string into groups randomly

給定一個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函數?

我不是C#專家所以我會給你一個純粹的數學解決方案,希望你能用你的語言翻譯它。

基本上你的任務由兩個獨立的部分組成:選擇b組i到j元素,以及隨機性。 第二個應該很簡單 - 只需隨機隨機洗牌,然后進行分組。 讓我們來看看有趣的部分:

如何將包含i b組中的n個元素分別分為j元素? 一個直接的解決方案是在ij之間取一個隨機數作為第一組元素的數量,然后是第二組等。但是,不能保證,這樣做你不會留下最后一組有元素數不在ij之間。 此類解決方案也不是純隨機分布。

正確的方法是獲取第一組元素的數量,當你采用盡可能多的元素時,尊重整體組分裂的解決概率 - 你基本上感興趣的是整個task(n, b, i, j)有多少解決方案task(n, b, i, j)如果我們假設我們在第一組中取k元素,那么task(nk, b-1, i, j)將存在多少。 如果我們只能計算解的數量,你可以用各自的概率取每個k,然后對第一組進行k的隨機抽樣,然后對第二組進行隨機抽樣,依此類推......

所以現在的問題是:有多少解決方案可用於task(n, b, i, j) 注意到task(n, b, i, j) = sum(k=i to j) task(nk, b - 1, i, j)這一事實你可以使用遞歸輕松找到這些數字(使用動態優化,這樣你不需要多次計算這些值)。

PS:對於解決方案的數量可能有一個封閉形式的解決方案,但我無法立即解決,只要n * b保持相對較小(<10 ^ 6),遞歸解決方案應該有效。

編輯
PS2:實際上task(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) )
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM