遇到此类问题时,最好从编辑器/IDE 中退后一步,在白板上画出一个简单的案例来思考问题。甚至不要做伪代码,只需画出一个流程图,说明这个问题的一个简单案例(例如a = 3)将如何一路龟缩。另外,一开始不要担心重复的组合。尝试找到一个可以为您提供所有所需组合的解决方案,然后改进您的解决方案以不给您重复。在这种情况下,为什么不看看a = 3 的可管理案例呢?让我为你画一个小图。绿色复选标记表示我们得到了一个有效的组合,红色叉号表示一个组合无效。
如您所见,我们从三个空子组合开始,然后通过为每个子组合附加一个数字来构建三个新的子组合。我们要检查所有可能的路径,因此我们选择 1、2 和 3,最终得到 [1]、[2] 和 [3]。如果组合中的数字之和等于 3,则我们找到了有效组合,因此我们可以停下来检查这条路径。如果组合中的数字之和超过3,则组合无效,我们也可以停止。如果两者都不是,我们只是继续构建组合,直到我们得出一个有效或无效的解决方案。
由于您的问题似乎主要是关于如何为此类问题制定递归解决方案,而不是关于特定语法的问题,而您恰好找到了 C++ 解决方案,我将在 Python 中提供解决方案(看起来几乎就像伪代码,它就是它所知道的)。
def getcombs(a, combo = None):
# initialize combo on first call of the function
if combo == None:
combo = []
combosum = sum(combo) # sum of numbers in the combo, note that sum([]) == 0
# simple case: we have a valid combination of numbers, i.e. combosum == a
if combosum == a:
yield combo # this simply gives us that combination, no recursion here!
# recursive case: the combination of numbers does not sum to a (yet)
else:
for number in range(1, a + 1): # try each number from 1 to a
if combosum + number <= a: # only proceed if we don't exceed a
extcombo = combo + [number] # append the number to the combo
# give me all valid combinations c that can be built from extcombo
for c in getcombs(a, extcombo):
yield c
让我们测试一下代码吧!
>>> combos = getcombs(3)
>>> for combo in combos: print(combo)
...
[1, 1, 1]
[1, 2]
[2, 1]
[3]
这似乎工作正常,a = 5 的另一个测试:
>>> combos = getcombs(5)
>>> for combo in combos: print(combo)
...
[1, 1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 2, 1]
[1, 1, 3]
[1, 2, 1, 1]
[1, 2, 2]
[1, 3, 1]
[1, 4]
[2, 1, 1, 1]
[2, 1, 2]
[2, 2, 1]
[2, 3]
[3, 1, 1]
[3, 2]
[4, 1]
[5]
解决方案包括我们正在寻找的所有七种组合,但代码仍然会产生重复项。您可能已经注意到,没有必要取一个小于之前选择的数字的数字来生成所有组合。因此,让我们添加一些代码,这些代码仅开始为不小于组合中当前最后一个数字的数字构建extcombo。如果组合为空,我们只需将前面的数字设置为 1。
def getcombs(a, combo = None):
# initialize combo on first call of the function
if combo == None:
combo = []
combosum = sum(combo) # sum of numbers in combo, note that sum([]) == 0
# simple case: we have a valid combination of numbers, i.e. combosum == a
if combosum == a:
yield combo # this simply gives us that combination, no recursion here!
# recursive case: the combination of numbers does not sum to a (yet)
else:
lastnumber = combo[-1] if combo else 1 # last number appended
for number in range(lastnumber, a + 1): # try each number between lastnumber and a
if combosum + number <= a:
extcombo = combo + [number] # append the number to the combo
# give me all valid combinations that can be built from extcombo
for c in getcombs(a, extcombo):
yield c
再一次,让我们测试一下代码!
>>> combo = getcombs(5)
>>> for combo in combos: print(combo)
...
[1, 1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 3]
[1, 2, 2]
[1, 4]
[2, 3]
[5]
提出的解决方案可能不是现有的最有效的解决方案,但希望它会鼓励您进行递归思考。逐步分解问题,为少量输入绘制一个简单案例,一次解决一个问题。