在多少种方法中,你可以将数字小于或等于N与n相等。解决这个问题的算法是什么?
实施例: 我们说我们有
n =10;
因此有很多组合,但例如我们可以这样做:
1+1+1+1+1+1+1+1+1+1 = 10
1+2+1+1+1+1+1+1+1=10
1+1+2+1+1+1+1+1+1=10
.....
1+9=10
10=10
8+2=10
等等。
如果您认为是加泰罗尼亚语问题,答案是:问题似乎是加泰罗尼亚问题,但事实并非如此。如果您看一下结果,您会看到N = 5在加泰罗尼亚算法中,您有14种可能性。但是在正确答案中,如果计算全部,则有2 ^ 4 = 16种可能性,如果仅保留唯一组合,则为斐波那契数组。例如N = 5我们有8种可能性,因此加泰罗尼亚算法不能验证。
这是我在一个有趣的测验中收到的问题,当时我认为解决方案是一个众所周知的公式,所以我失去了很多时间试图记住它:) 我找到了2个解决这个问题的方法,如果你只考虑独特的组合,我会找到1个。例如2 + 8与8 + 2相同,你只考虑其中的1个。 那么解决它的算法是什么?
答案 0 :(得分:1)
我想要的所有3种解决方案都使用数学归纳法:
解决方案1:
if n =0 comb =1
if n =1 comb = 1
if n=2 there are 1+1, 2 comb =2 = comb(0)+comb(1)
if n=3 there are 1+1+1, 1+2, 2+1, 3 comb = 4 = comb(0)+comb(1)+comb(2)
if n=4 there are 1+1+1+1, 1+2+1,1+1+2,2+1+1,2+2,1+3,3+1,4 comb = 8 =comb(0)+comb(1)+comb(2)+comb(3)
现在我们在这里看到一个模式:
at k value we have comb(k)= sum(comb(i)) where i between 0 and k-1
using math induction we can prove it for k+1 that:
comb(k+1)= sum(comb(i)) where is is between 0 and k
解决方案编号2:
如果我们多关注解决方案1,我们可以说:
comb(0)=2^0
comb(1)=2^0
comb(2)=2^1
comb(3)=2^2
comb(4)=2^3
comb(k)=2^(k-1)
again using the math induction we can prove that
comb(k+1)=2^k
解决方案编号3(如果我们只保留唯一组合),我们可以看到:
comb(0)=1
comb(1)=1
comb(2)= 1+1,2=2
comb(3)= 1+1+1, 1+2, 2+1, 3 we take out 1+2 because we have 2+1 and its the same comb(3)=3
comb(4) = 1+1+1+1, 1+2+1,1+1+2,2+1+1,2+2,1+3,3+1,4, here we take out the 1+2+1,,2+1+1 and 1+3 because we have them but in different order comb(4)= 5.
如果我们继续,我们可以看到:
comb(5) = 8
comb(6)=13
我们现在可以看到以下模式:
comb (k) = comb (k-1) + comb(k-2) the Fibonacci array
again using Math induction we can prove that for k+1
comb(k+1) = comb(k)+comb(k-1)
现在,使用2个解决方案的递归或仅使用2 ^ k的解决方案的非递归方法,可以很容易地用语言实现这些解决方案。
顺便说一下,这与图论有着密切的联系(你可以从一个更大的图开始构建多少个子图 - 我们的数字N,以及子图是计算的方法)
太棒了不是吗?
答案 1 :(得分:1)
这是一个有趣的问题。我还没有解决方案,但我认为这可以通过分而治之的方式完成。如果您将问题空间视为二叉树,则可以按如下方式生成:
根是整数n 它的孩子是地板(n / 2)和ceil(n / 2)
示例:强> N = 5
5
/ \
2 3
/ \ / \
1 1 1 2
/ \
1 1
如果以递归方式执行此操作,则会获得二叉树。然后,如果可以以这种方式遍历树,以获得总结为n的所有可能组合:
get_combinations(root_node)
{
combinations=[]
combine(combinations, root_node.child_left, root_node.child_right)
}
combine(combinations, nodeA, nodeB)
{
new_combi = "nodeA" + "+nodeB"
combinations.add(new_combi)
if nodeA.has_children(): combinations.add( combine(combinations, nodeA.child_left, nodeA.child_right) + "+nodeB" )
if nodeB.has_children(): combinations.add( "nodeA+" + combine(combinations, nodeB.child_left, nodeB.child_right) )
return new_combi
}
这只是一个草案。你知道,你不必事先明确地生成树,但是你可以沿途做到这一点。如果我找到时间,也许我可以提出一个更好的算法。
修改强>
好的,我没有完全回答OP问题,但是我不想留下未完成的东西,所以在这里我将我的解决方案作为一个有效的python程序:
import math
def print_combinations(n):
for calc in combine(n):
line = ""
count = 0
for op in calc:
line += str(int(op))
count += 1
if count < len(calc):
line += "+"
print line
def combine(n):
p_comb = []
if n >= 1: p_comb.append([n])
if n >1:
comb_left = combine(math.floor(n/float(2)))
comb_right = combine(math.ceil(n/float(2)))
for l in comb_left:
for r in comb_right:
lr_merge = []
lr_merge.extend(l)
lr_merge.extend(r)
p_comb.append(lr_merge)
return p_comb
现在,您可以使用数字&lt; = n 生成所有可能的方法来总结 n 。例如,如果您想为 n = 5 执行此操作,请将其命名为:print_combinations(5)
玩得开心,但请注意,你会很快遇到内存问题(动态编程以拯救!)并且你可以进行等效计算(例如1 + 2和2 + 1)。