[英]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.