【问题标题】:How can I make this code more efficent for the coding challenge?我怎样才能使这段代码更有效地应对编码挑战?
【发布时间】:2019-05-05 12:00:27
【问题描述】:

我正在做名为 Integers: Recreation One in Codewars 的编码挑战。

Challenge => 给定两个整数 m, n (1

def list_squared(m, n):
    lst = list()
    for num in range(m, n+1):
        total= 0
        for i in range(1, num//2 +1):
            if num % i == 0:
                total += i**2
        total += num**2

        if (total**(1/2)) % 1 == 0:
            lst.append([num, total])

    return lst

我的代码适用于示例测试,但是当我尝试提交它时,它给了我“执行超时”错误。我想我必须提高效率,但不知道该怎么做。如何让代码更高效?

【问题讨论】:

  • 不会更快,但我觉得第二个循环要么是range(1,num+1),要么应该是total+=i**2+(num/i)**2,如果本身是平方数,最后减去num .在这两种情况下,total+=num**2 行都感觉不对。
  • 啊,对于total+=i**2+(num/i)**2 变体,内部循环不应该转到num/2,而是转到sqrt(num)。我认为这就是事情可以变得更快的地方。
  • @SuperKogito 1) 那个话题是Ruby,这个问题是Python。 2)该主题中公认的答案产生了错误的结果,每个人似乎都对此非常满意....
  • 我的错,我刚读了这个问题,它很相似。

标签: python


【解决方案1】:

sqrt 理念的实现:

def list_squared(m, n):
    lst = list()
    for num in range(m, n+1):
        total = 0
        sqrt = int(math.sqrt(num))
        for i in range(1, sqrt+1):
            q,r=divmod(num,i)
            if r == 0:
                total += i*i + q*q
        if sqrt*sqrt == num:
            total -= num

        if math.sqrt(total) % 1 == 0:
            lst.append([num, total])

    return lst

它似乎工作。一些可能有意义或可能没有意义的事情:

  • 不知道**(1/2)还是math.sqrt性能更好,可以查一下。但是我觉得sqrt 更具可读性。当然如果你不允许使用数学库,坚持**
  • 很有可能x*xx**2快,也可以检查一下
  • 在汇编级别,商和余数是在一个步骤中生成的,这对于 Python 可能是正确的,也可能不是。然而这就是我使用divmod 的原因(所以q*q 替换(num/i)*(num/i)(num/i)**2

实际上这些细节可能根本不重要,缩短内循环应该是主要技巧。


@H.E.K.:您“感觉”循环可以通过 /2 以某种方式缩短,但实际上它必须是平方根。
如果inum 的除数,则num/i 也是num 的除数。如果i1 开始增加,num/inum/1 开始减少(所以从num 本身开始)。随着时间的推移,他们会在某个地方相遇,那就是sqrt(num)。在sqrt(num) 之上增加i 最终会检查您已经看到的除数对。 以 20 为例:
i   20/i
1   20
2   10
3   <something fraction>
4   5    <--- this is the last step when we encounter a new divisor
5   4    <--- here the divisors are "old", we have seen 4 and 5 already
6   <something fraction>
......

所以除数是 1,20,2,10,4,5 - 我们不必单独检查 5...20,检查 1...4=(int)sqrt(20) 就足够了,这是一个很大的收获。

【讨论】:

  • 那行得通,但我不能完全理解你在内部循环和之后做了什么。你能给我解释一下吗?
  • @H.E.K 好的,我添加了一些解释
  • @tevedamar 非常感谢。现在我完全明白你做了什么。再次感谢您
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多