我正在尝试完成以下挑战:https://app.codesignal.com/challenge/ZGBMLJXrFfomwYiPs。 我编写的代码似乎可以正常工作,但是效率很低,以至于无法通过测试(执行时间太长,使用的内存过多)。有什么方法可以提高效率?我对构建高效的脚本还很陌生。可以使用提到的“ map()”代替“ for range(1,n)中的i”。感谢Xero Smith和其他人到目前为止提出的优化建议:
from functools import reduce
from operator import mul
from itertools import combinations
# Starting from the maximum, we can divide our bag combinations to see the total number of integer factors
def prime_factors(n):
p = 2
dct = {}
while n != 1:
if n % p:
p += 1
else:
dct[p] = dct.get(p, 0) + 1
n = n//p
return dct
def number_of_factors(n):
return reduce(mul, (i+1 for i in prime_factors(n).values()), 1)
def kinderLevon(bags):
candies = list()
for x in (combinations(bags, i) for i in range(1, len(bags)+1)):
for j in x:
candies.append(sum(j))
satisfied_kids = [number_of_factors(i) for i in candies]
return candies[satisfied_kids.index(max(satisfied_kids))]
任何帮助将不胜感激。
谢谢
亚伦
答案 0 :(得分:2)
在我的评论之后,我已经可以确定内存和复杂性方面的改进。在factors
函数中,由于您只需要数量的因子,因此只能计算它们而不是存储它们。
def factors(n):
k = 2
for i in range(2, n//2 +1):
if n % i == 0:
k += 1
return k
编辑:如注释中所述,请尽早停止计数器。
这实际上降低了大量数字的时间复杂性,但实际上并没有降低较小的数字。
这比使用列表推导(仍然分配内存)的改进要好得多
此外,两次分配组合列表毫无意义。你在做
x = list(combinations(bags, i));
for j in list(x):
...
将元组(由combinations
返回)转换为列表的第一行,从而复制数据。第二行list(x)
重新分配该列表的副本,从而占用更多内存!在那里,您实际上应该只写:
for j in combination(bags, i):
...
就语法而言,请不要在Python中使用分号;
!
答案 1 :(得分:1)
使用列表推导。因子函数可以这样转换:
def factors(n):
return len([i for i in range(1, n + 1) if n % i == 0])
答案 2 :(得分:1)
首先,组合是可迭代的。这意味着您无需遍历它们就可以将它们转换为列表。实际上,这样做效率极低。
接下来可以显着改善的是您的factors
过程。目前它是线性的。我们可以做得更好。我们可以通过以下算法获得整数N
的因数:
N
的素因式分解,使得N = p1^n1 * p2^n2 * ...
N
的因子数为(1+n1) * (1+n2) * ...
有关详细信息,请参见https://www.wikihow.com/Find-How-Many-Factors-Are-in-a-Number。
还有其他事情,您当前的解决方案包含许多未使用的变量和计算。摆脱它们。
有了这些,我们得到以下应该起作用的东西:
from functools import reduce
from operator import mul
from itertools import combinations
# Starting from the maximum, we can divide our bag combinations to see the total number of integer factors
def prime_factors(n):
p = 2
dct = {}
while n != 1:
if n % p:
p += 1
else:
dct[p] = dct.get(p, 0) + 1
n = n//p
return dct
def number_of_factors(n):
return reduce(mul, (i+1 for i in prime_factors(n).values()), 1)
def kinderLevon(bags):
candies = list()
for x in (combinations(bags, i) for i in range(1, len(bags)+1)):
for j in x:
candies.append(sum(j))
satisfied_kids = [number_of_factors(i) for i in candies]
return candies[satisfied_kids.index(max(satisfied_kids))]