简体   繁体   English

如何使 Python 代码更高效?

[英]How can I make Python code more efficient?

Newbie here.新手来了I have this code, that displays all possible sums to reach a certain number.我有这个代码,它显示达到某个数字的所有可能的总和。 But its complexity is too high and it takes too longe when numbers are too high.但是它的复杂度太高,当数字太高时需要太长时间。 How can I refactor this to something more simple?我怎样才能把它重构为更简单的东西?

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)

output:输出:

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

The recursive version could be like this:递归版本可能是这样的:

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

Test:测试:

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)]

The idea to decompose the problem: a set of combinations can be written as a number concatenated with all the combinations for which the sum is n minus that first number.分解问题的想法:一组组合可以写成一个数字,该数字与所有组合的总和为n减去第一个数字。

A simpler code without dealing with repetition could be like this:不处理重复的更简单的代码可能是这样的:

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

which gives:这使:

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

(1, 2) and (2, 1) are similar, to prevent this a i_max argument is added (see the first function). (1, 2)(2, 1)类似,为了防止这种情况,添加了i_max参数(参见第一个函数)。 The idea here is to go always in descending order.这里的想法是始终按降序排列。 A number on the right is always equal or smaller than a number on the left.右边的数字总是等于或小于左边的数字。 This maximum number is passed as an argument, and the loop start with it instead of the total sum asked.这个最大数字作为参数传递,循环从它开始,而不是要求的总和。

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

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