当试图解决项目Euler时,python运行时间非常慢.不确定是python还是慢速算法



我想解决的问题是问题87。这个问题要求你找到素数三元组和低于50000000。到目前为止,代码已经运行了10多分钟,足够写这篇文章了。

28=2^2+2^3+2^4

33=3^2+2^3+2^4

49=5^2+2^3+2^4

47=2^2+3^3+2^4

在我的强力方法中,我对其进行了优化,只检查小于50000000的平方、立方体和夸脱值。我用筛子生成7071的数字,这不需要很长时间。

def algo(primes_matrix):
    suma = []
    counter2 = 0;
    limit = 50000000
    # square max, primes_matrix[907][1] = 7041
    # cube max,  primes_matrix[72][2]   = 368
    # quart max, primes_matrix[22][3]   = 84
    for n2 in range(0, len(primes_matrix)-1):  # loop power 2
        for n3 in range(0, 72):        # loop power 3
            for n4 in range(0, 22):    # loop power 4
                
                add = primes_matrix[n2][1] + primes_matrix[n3][2]
                if(add<limit):
                    add+=primes_matrix[n4][3]
                    if(add<limit):
                        if add not in suma:
                            suma.append(add)
                            counter2+=1
    print "counter =",counter2

我才刚开始学习Python,所以我宁愿正常使用C/C++来解决这类问题,因为我相信它会执行得更快。是这样吗?或者更确切地说,我是滥用了Python的一些函数,使其运行速度比应该的慢得多,还是在某种程度上扰乱了我的算法。无论如何,我会尝试在C中重新实现它,看看有什么不同。谢谢你的帮助!

没有足够的信誉来评论,但使用集合"in"是一个平均查找接近O(1)的哈希函数,而列表"in"需要O(n)。这个问题的Python解决方案可以很容易地运行不到一秒钟。我将列出其他几个需要考虑的优化:

  1. add=素数矩阵[n2][1]+素数矩阵[n3][2]应该在for n4…循环之外,因为它的值不会更改,并且您正在重新计算它
  2. 只要add已经大于限制,就中断循环,而不是继续迭代

我不知道这是否有帮助,因为我无法真正测试我要说的任何内容,但是。。。。

看起来你应该放置

add = primes_matrix[n2][1] + primes_matrix[n3][2]

n4循环之外,因为它独立于它。无需重新计算22次。


看起来add也可以由您迭代的列表来表示,这意味着您可以通过使用列表理解来节省时间,而不是嵌套的for循环,即代替:

for n2 in range(0, len(primes_matrix)-1):  # loop power 2
    for n3 in range(0, 72):      
     ...
        add = primes_matrix[n2][1] + primes_matrix[n3][2]

尝试:

 add_list = [primes_matrix[n2][1] + primes_matrix[n3][2] for n2 in range(0, len(primes_matrix)-1) for n3 in range(0, 72)]
 for add in add_list:
     for n4 in range(22):
         ...

也许您想用集合代替suma,而不是使用列表。我认为在一个集合中添加元素应该更快,尽管我从来没有这样的计时。


为什么不突破n4循环一次add > limit-即

for n4 in range(0, 22):
   ...
   if (add >= limit):
      break

我认为你只需要在n4循环中进行1次if (add < limit)检查

 for n4 in range(22):
    add+=primes_matrix[n4][3]
    if (add <= limit):
       if add not in suma:
         suma.append(add) # Or suma.add(add) if suma is a set - perhaps a variable name other than add would be good
         counter2+=1
    else:
      break #add > limit, so no need to keep looping through n4

好吧,这几乎就是我的全部了。我可以看到,其中一些在其他答案中得到了回应(前面),但HTH

最新更新