此問題非常適合遞歸解決方案。
通常情況下的解決方案是通過採用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數字一一對應。 – 2012-07-06 11:00:30
我同意@MarkoTopolnik。但是,這幾乎是一個常見問題,所以我投票結束。 – 2012-07-06 11:07:02
[重複變異的代碼(combinatorics)的可能的重複?](http://stackoverflow.com/questions/2366074/code-for-variations-with-repetition-combinatorics) – 2012-07-06 11:07:59