简体   繁体   English

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

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

Given a set of integers 1,2, and 3, find the number of ways that these can add up to n. 给定一组整数1,2和3,请找出它们加起来为n的方式数。 (The order matters, ie say n is 5. 1+2+1+1 and 2+1+1+1 are two distinct solutions) (顺序很重要,即n为5。1 + 2 + 1 + 1和2 + 1 + 1 + 1是两个不同的解决方案)

My solution involves splitting n into a list of 1s so if n = 5, A = [1,1,1,1,1]. 我的解决方案涉及将n拆分为1的列表,因此如果n = 5,则A = [1,1,1,1,1]。 And I will generate more sublists recursively from each list by adding adjacent numbers. 通过添加相邻数字,我将从每个列表中递归地生成更多子列表。 So A will generate 4 more lists: [2,1,1,1], [1,2,1,1], [1,1,2,1],[1,1,1,2], and each of these lists will generate further sublists until it reaches a terminating case like [3,2] or [2,3] 因此,A将再生成4个列表:[2,1,1,1],[1,2,1,1],[1,1,2,1],[1,1,1,2],以及每个这些列表中的一个将生成进一步的子列表,直到达到[3,2]或[2,3]之类的终止情况

Here is my proposed solution (in Python) 这是我建议的解决方案(在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)))

May I know if I'm on the right track, and if so, is there any way to make this code more efficient? 我是否可以确定我的工作是否正确,是否可以提高此代码的效率?

Please note that this is not a coin change problem. 请注意,这不是找零硬币的问题。 In coin change, order of occurrence is not important. 在硬币找零中,出现的顺序并不重要。 In my problem, 1+2+1+1 is different from 1+1+1+2 but in coin change, both are same. 在我的问题中,1 + 2 + 1 + 1与1 + 1 + 1 + 2不同,但是在硬币找零时,两者相同。 Please don't post coin change solutions for this answer. 请不要为此问题发布硬币找零解决方案。

Edit: My code is working but I would like to know if there are better solutions. 编辑:我的代码正在工作,但我想知道是否有更好的解决方案。 Thank you for all your help :) 谢谢你的帮助 :)

The recurrence relation is F(n+3)=F(n+2)+F(n+1)+F(n) with F(0)=1, F(-1)=F(-2)=0. 递归关系为F(n + 3)= F(n + 2)+ F(n + 1)+ F(n),其中F(0)= 1,F(-1)= F(-2)= 0 。 These are the tribonacci numbers (a variant of the Fibonacci numbers): 这些是Tribonacci数(Fibonacci数的变体):

It's possible to write an easy O(n) solution: 可以编写一个简单的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

It's harder, but possible to compute the result in relatively few arithmetic operations: 这比较困难,但是可以用较少的算术运算来计算结果:

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)

The idea that you describe sounds right. 您描述的想法听起来很正确。 It is easy to write a recursive function that produces the correct answer..slowly. 很容易编写一个递归函数来缓慢地产生正确的答案。

You can then make it faster by memoizing the answer. 然后,您可以通过记住答案来使其更快。 Just keep a dictionary of answers that you've already calculated. 只需保留已经计算出的答案字典即可。 In your recursive function look at whether you have a precalculated answer. 在递归函数中,查看您是否有预先计算的答案。 If so, return it. 如果是这样,请将其退回。 If not, calculate it, save that answer in the dictionary, then return the answer. 如果不是,请进行计算,然后将该答案保存在词典中,然后返回答案。

That version should run quickly. 该版本应该可以快速运行。

An O(n) method is possible: O(n)方法是可能的:

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

The idea is that we can work out how many ways of making a sequence with n by considering each choice (1,2,3) for the last partition size. 这个想法是,通过考虑最后一个分区大小的每个选择(1,2,3),我们可以得出用n构成序列的多少种方法。

eg to count choices for (1,1,1,1) consider: 例如,计算(1,1,1,1)的选择,请考虑:

  1. choices for (1,1,1) followed by a 1 (1,1,1)的选择,然后是1
  2. choices for (1,1) followed by a 2 (1,1)的选择,然后是2
  3. choices for (1) followed by a 3 (1)的选择,然后是3

If you need the results (instead of just the count) you can adapt this approach as follows: 如果您需要结果(而不只是计数),可以按以下方式调整此方法:

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.

相关问题 如何在列表中找到成对的整数,这些整数加起来为 O(N) 中的目标? - How to find pairs of integers in a list that add up to a target in O(N)? 如何获得一个 ndarray,其中包含将 N 个元素加起来的不同方法? - How can I get a ndarray which contains the different ways of adding up to N a certain number of elements? 有没有办法递归地找到一组数字可以加起来为某个数字的不同方式? - Is there a way to recursively find the different ways a set of numbers can add up to a certain number? 如何将此代码的递归应用于求和“ N”的方式数量? - How to apply recursion to this code about the number of ways to sum up to 'N'? 如何为每个 ID 分配一个组号(n=1,2,3.....)? - How to assign a group number to each ID (n=1,2,3.....)? 打印从 1 到 n 的整数(给定数字) - Print the integers from 1 up to n (given number) 如何使用数组找到前 n 个负整数 - How can i find the first n negative integers by using an array 查找可以重排序列的方式数量 - Find the number of ways a sequence can be rearranged 如何计算将字符串分成任意大小的 N 个部分的方法数? - How can I count the number of ways to divide a string into N parts of any size? 递归:找到在列表中添加元素以达到 n 的所有方法 - recursion: find all ways to add elements in an list to get to n
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM