繁体   English   中英

这段代码效率太低,如何提高内存和执行效率?

[英]This code is too inefficient, how can I increase memory and execution efficiency?

我正在尝试完成以下挑战: https//app.codesignal.com/challenge/ZGBMLJXrFfomwYiPs 我编写的代码似乎有效,但是它的效率很低,以至于它无法通过测试(执行时间太长而使用的内存太多)。 我有什么方法可以提高效率吗? 我很擅长构建高效的脚本。 有人提到“map()”可以代替“for i in range(1,n)”。 感谢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))]

任何帮助将不胜感激。

谢谢,

亚伦

根据我的评论,我已经可以确定内存和复杂性的改进。 在您的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中!

使用列表推导。 因子函数可以像这样转换:

def factors(n):
    return len([i for i in range(1, n + 1) if n % i == 0])

首先,组合是可迭代的。 这意味着您不必在迭代它们之前将它们转换为列表; 事实上,这样做非常低效。

接下来可以显着改善的是你的factors程序。 目前它是线性的。 我们可以做得更好。 我们可以通过以下算法得到整数N的因子数:

  1. 得到N的素因子分解,使得N = p1^n1 * p2^n2 * ...
  2. 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))]

暂无
暂无

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

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