有多少种方法可以使用数字< = N来计算直到N.

时间:2014-06-25 08:44:38

标签: algorithm

在多少种方法中,你可以将数字小于或等于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个。 那么解决它的算法是什么?

2 个答案:

答案 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)。