「貪婪」算法對此很有效。我使用Python 3瀏覽:
def pick(total):
def inner(highest, total):
if total == 0:
yield result
return
if highest == 1:
result[0] = total
yield result
result[0] = 0
return
for i in reversed(range(total // highest + 1)):
result[highest - 1] = i
newtotal = total - i * highest
yield from inner(min(highest - 1, newtotal),
newtotal)
result = [0] * total
yield from inner(total, total)
然後,例如,
for x in pick(5):
print(x)
顯示:
[0, 0, 0, 0, 1]
[1, 0, 0, 1, 0]
[0, 1, 1, 0, 0]
[2, 0, 1, 0, 0]
[1, 2, 0, 0, 0]
[3, 1, 0, 0, 0]
[5, 0, 0, 0, 0]
最喜歡的遞歸算法,它更或多或少顯而易見的事情,然後遞歸解決剩下的(子)問題。
這裏inner(highest, total)
表示使用不大於highest
的整數找到total
的所有分解。我們可以使用多少份highest
?這個比較明顯的答案是,我們可以使用0,1,2,...,直到(包括)total // highest
副本,但不超過這個。除非highest
是1 - 那麼,我們必須使用的1
我們使用的highest
然而,許多副本究竟total
份,其餘的子問題分解使用整數總的一切依然不比highest - 1
大。通過min(highest - 1, newtotal)
而不是highest - 1
是一種優化,因爲嘗試任何大於新總數的整數都是毫無意義的。
@idjaw:存在實際問題(即效率)。我的理解是[效率問題在堆棧溢出上是有效的](http://meta.stackexchange.com/questions/215282/is-stack-overflow-the-right-place-to-ask-a-question-about-碼效率)。 – user3277533
我編輯了問題的開頭,使其更清晰。請注意,關於組合生成的問題通常是這樣的:顯示暴力代碼的代碼是無用的:這既是顯而易見的,也是無益的。很高興聽到OP的聲明:「我已經實施了一種生成所有排列組合的強力方法,然後檢查列表是否滿足上述要求」,並且很高興他們不費心去展示它;-)高效在這個領域中的代碼(他們問的)通常與僅僅有效的暴力代碼幾乎沒有任何關係。 –