繁体   English   中英

如何找到整数1,2,3可以累加n的方式?

[英]How to find number of ways that the integers 1,2,3 can add up to n?

给定一组整数1,2和3,请找出它们加起来为n的方式数。 (顺序很重要,即n为5。1 + 2 + 1 + 1和2 + 1 + 1 + 1是两个不同的解决方案)

我的解决方案涉及将n拆分为1的列表,因此如果n = 5,则A = [1,1,1,1,1]。 通过添加相邻数字,我将从每个列表中递归地生成更多子列表。 因此,A将再生成4个列表:[2,1,1,1],[1,2,1,1],[1,1,2,1],[1,1,1,2],以及每个这些列表中的一个将生成进一步的子列表,直到达到[3,2]或[2,3]之类的终止情况

这是我建议的解决方案(在Python中)

ways = []
def check_terminating(A,n):
    # check for terminating case
    for i in range(len(A)-1):
        if A[i] + A[i+1] <= 3:
            return False # means still can compute
    return True

def count_ways(n,A=[]):
    if A in ways:
       # check if alr computed if yes then don't compute
       return True
    if A not in ways: # check for duplicates
        ways.append(A) # global ways
    if check_terminating(A,n):
        return True # end of the tree
    for i in range(len(A)-1):
        # for each index i,
        # combine with the next element and form a new list
        total = A[i] + A[i+1]
        print(total)
        if total <= 3:
            # form new list and compute
            newA = A[:i] + [total] + A[i+2:]
            count_ways(A,newA)
            # recursive call

# main            
n = 5
A = [1 for _ in range(n)]

count_ways(5,A)
print("No. of ways for n = {} is {}".format(n,len(ways)))

我是否可以确定我的工作是否正确,是否可以提高此代码的效率?

请注意,这不是找零硬币的问题。 在硬币找零中,出现的顺序并不重要。 在我的问题中,1 + 2 + 1 + 1与1 + 1 + 1 + 2不同,但是在硬币找零时,两者相同。 请不要为此问题发布硬币找零解决方案。

编辑:我的代码正在工作,但我想知道是否有更好的解决方案。 谢谢你的帮助 :)

递归关系为F(n + 3)= F(n + 2)+ F(n + 1)+ F(n),其中F(0)= 1,F(-1)= F(-2)= 0 。 这些是Tribonacci数(Fibonacci数的变体):

可以编写一个简单的O(n)解决方案:

def count_ways(n):
    a, b, c = 1, 0, 0
    for _ in xrange(n):
        a, b, c = a+b+c, a, b
    return a

这比较困难,但是可以用较少的算术运算来计算结果:

def count_ways(n):
    A = 3**(n+3)
    P = A**3-A**2-A-1
    return pow(A, n+3, P) % A

for i in xrange(20):
    print i, count_ways(i)

您描述的想法听起来很正确。 很容易编写一个递归函数来缓慢地产生正确的答案。

然后,您可以通过记住答案来使其更快。 只需保留已经计算出的答案字典即可。 在递归函数中,查看您是否有预先计算的答案。 如果是这样,请将其退回。 如果不是,请进行计算,然后将该答案保存在词典中,然后返回答案。

该版本应该可以快速运行。

O(n)方法是可能的:

def countways(n):
    A=[1,1,2]
    while len(A)<=n:
        A.append(A[-1]+A[-2]+A[-3])
    return A[n]

这个想法是,通过考虑最后一个分区大小的每个选择(1,2,3),我们可以得出用n构成序列的多少种方法。

例如,计算(1,1,1,1)的选择,请考虑:

  1. (1,1,1)的选择,然后是1
  2. (1,1)的选择,然后是2
  3. (1)的选择,然后是3

如果您需要结果(而不只是计数),可以按以下方式调整此方法:

cache = {}
def countwaysb(n):
    if n < 0:
        return []
    if n == 0:
        return [[]]
    if n in cache:
        return cache[n]
    A = []
    for last in range(1,4):
        for B in countwaysb(n-last):
            A.append(B+[last])
    cache[n] = A   
    return A

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM