CodeWars Python 3.6代码的优化:整数:一个Recreation One

时间:2018-12-18 03:56:54

标签: python-3.x optimization

我需要帮助优化Code​​Wars Integers:Recreation One Kata的python 3.6代码。

我们得到了一个数字范围,我们必须返回数字和除数平方的和,即平方本身。

“ 42的除数是:1、2、3、6、7、14、21、42。这些平方的平方是:1、4、9、36、49、196、441、1764。平方除数是2500,即50 * 50,是一个正方形!

给出两个整数m,n(1 <= m <= n),我们想找到m和n之间的所有整数,它们的平方除数之和本身就是一个平方。 42就是这样一个数字。”

我的代码适用于各个测试,但是在提交时超时:

def list_squared(m, n):
    sqsq = []
    for i in range(m, n):
        divisors = [j**2 for j in range(1, i+1) if i % j == 0]
        sq_divs = sum(divisors)
        sq = sq_divs ** (1/2)
        if int(sq) ** 2 == sq_divs:
            sqsq.append([i, sq_divs])

    return sqsq

2 个答案:

答案 0 :(得分:0)

更多的是数学问题。 i 的两个最大除数是 i 本身和 i / 2 。因此,仅使用i // 2 + 1作为范围停止而不是i + 1,就可以使代码加速两次。只是不要忘记为sq_divs增加i ** 2。 您可能希望获得一些微小的性能改进,但不包括sq变量和sq_divs ** (1/2)

顺便说一句,您应该在第一个范围内使用n + 1个停止位置。

def list_squared(m, n):
    sqsq = []
    for i in range(m, n+1):
        divisors = [j * j for j in range(1, i // 2 + 1 #speed up twice
            ) if i % j == 0]
        sq_divs = sum(divisors)
        sq_divs += i * i #add i as divisor
        if ((sq_divs) ** 0.5) % 1 == 0: #tiny speed up here
            sqsq.append([i, sq_divs])
    return sqsq

UPD:我已经尝试过Kata,但仍然超时。因此,我们需要更多的数学运算!如果 i 可以除以 j ,那么它也可以除以 i / j ,因此我们可以使用 sqrt(i)< / strong>(int(math.sqrt(i)) + 1))作为范围停止。 if i % j == 0,然后将j * j追加到除数数组。 AND if i / j != j,然后附加(i / j) ** 2

答案 1 :(得分:0)

通过将最大范围设置为O(N)而非O(Log((N)),可以将列表理解中的循环复杂度从sqrt(num)+1降低到num

通过从 1循环到sqrt(num)+1 ,我们可以得出结论,如果 i (循环中的当前项)是 num的因数,那么 num除以i 必须是另一个。

例如:2是10的因数,所以5(10/2)

以下代码通过了所有测试:

import math

def list_squared(m, n):
    result = []
    for num in range(m, n + 1):
        divisors = set()
        for i in range(1, int(math.sqrt(num)+1)):
            if num % i == 0:
                divisors.add(i**2)
                divisors.add(int(num/i)**2)
        total = sum(divisors)
        sr = math.sqrt(total)
        if sr - math.floor(sr) == 0:
            result.append([num, total])
    return result