如何提高Python代码的效率?

时间:2018-08-28 14:26:36

标签: python

新手在这里。 我有这段代码,它显示所有可能的总和以达到一定数量。 但是它的复杂性太高了,而当数字太高时它会花费很长时间。如何将其重构为更简单的内容?

import itertools

def combos(n):

    result = []
    for i in range(n,0,-1):
        for seq in itertools.combinations_with_replacement(range(1,n+1), i):
            if sum(seq) == n:
                seq = list(seq)
                result.append(seq)
    return(result)

combos(4)

输出:

[[1,1,1,1],[1,1,2],[1,3],[2,2],[4]]

1 个答案:

答案 0 :(得分:0)

递归版本可能是这样的:

def combinations_max_sum(sum_max, i_max=None):

    if sum_max == 0:
        return [()]

    if not i_max or i_max > sum_max:
        i_max = sum_max

    combinations = [(i, *right_part)
                    for i in range(i_max, 0, -1)
                    for right_part in combinations_max_sum(sum_max-i, i_max=i)]

    return combinations

测试:

print(combinations_max_sum(4)) # [(4,), (3, 1), (2, 2), (2, 1, 1), (1, 1, 1, 1)]
print(combinations_max_sum(4, i_max=1)) # [(1, 1, 1, 1)]
print(combinations_max_sum(5))
# [(5,), (4, 1), (3, 2), (3, 1, 1), (2, 2, 1), (2, 1, 1, 1), (1, 1, 1, 1, 1)]

分解问题的想法:一组组合可以写为一个数字,该数字与所有组合的和为n减去第一个数字。

一个简单的无需重复处理的代码可能是这样的:

def combinations_with_repetition(n):

    if n == 0:
        return [()]

    combinations = [(i, *right_part)  # concatenation
                    for i in range(1, n+1)  # for all possible first number 
                    for right_part in combinations_with_repetition(n-i)]
                    # ^ all possible combinations
                    #   given the first number i

    return combinations

给出:

combinations_with_repetition(3)
# [(1, 2), (1, 1, 1), (2, 1), (3,)]

(1, 2)(2, 1)是相似的,以防止添加i_max参数(请参阅第一个函数)。这里的想法是始终按降序排列。右边的数字始终等于或小于左边的数字。该最大值作为参数传递,循环从该最大值开始,而不是要求的总和。