簡體   English   中英

K個項目可以在N個插槽中排列的所有可能方式

[英]all possible ways in which K items can be arranged in N slots

我正在尋找一種算法來找到N個項目的K值的所有組合。

例:

K值是[R,B]和N是2所以得到{RR,RB,BR,BB} 2 * 2 = 4種方式

K值是[R,B]和N是3所以得到{RRR,RRB,RBB,RBR,BRR,BRB,BBR,BBB} 2 * 2 * 2 = 8種方式

我需要找出通用算法來找到K個項目可以在N個槽中排列的所有可能方式。 (允許重復)

另一個例子是:

K值是[R,G,B]和N是5所以我需要找到3 ^ 5 = 81種組合。

這個問題非常適合遞歸解決方案。

一般情況下的解決方案通過采用N - 1的解決方案清楚地形成,然后將每個集合的元素依次預先計算結果。 在偽代碼中:

f(options, 0) = []
f(options, n) = options foreach o => o ++ f(options, n-1)

這可以在Java中以遞歸方式實現,但是對於中等大小的n值,您會遇到堆棧溢出錯誤; 我還懷疑JIT編譯器在優化遞歸算法方面效率較低,因此性能會受到影響。

但是,遞歸算法總是可以轉換為循環等價物。 在這種情況下,它可能看起來像:

List<String> results = new ArrayList<String>();
results.add(""); // Seed it for the base case n=0
for (int i = 0; i < n; i ++) {
    List<String> previousResults = results;
    results = new ArrayList<String>();
    for (String s : options) {
       for (String base : previousResults) {
           results.add(s + base);
       }
    }
}
return results;

這種方法(我希望!)與遞歸方法類似 - 在每次迭代時它將當前進度(即n-1的結果)“保存”到previousResults ,然后依次遍歷選項,以獲得前置結果他們以前的結果。

通過任何自動遞歸到迭代算法傳遞遞歸解決方案的效果會很有趣,並將可讀性和性能與這個手工創建的算法進行比較。 這留給讀者練習。

我將使用基本桶中的N位計數器:k = 3,n = 5

(0,0,0,0,0)
(0,0,0,0,1),
....
(2,2,2,2,2)

實現這樣的計數器很簡單,只需保持大小為n + 1的數組,首先將所有元素設置為零,每次增加最新元素,如果它將超過k-1,則增加下一個鄰居(直到鄰居超過k-1) )。 當n + 1個元素設置為1時,操作終止。

如果您嘗試過但無法這樣做,請通過評論告訴它。

暫無
暫無

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

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