尝试解决项目Euler时非常慢的python运行时间。不确定python还是慢算法

时间:2015-12-27 02:15:57

标签: python algorithm performance

我想解决的问题是problem 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中重新实现它以查看差异。谢谢你的帮助!

2 个答案:

答案 0 :(得分:6)

没有足够的声誉来评论,但使用一组“in”是一个散列函数,其平均查找接近于O(1),而列表“in”需要O(n)。针对此问题的Python解决方案可以在一秒钟内轻松运行。我将列出其他几个要考虑的优化:

  1. add = primes_matrix [n2] [1] + primes_matrix [n3] [2] 应该在for n4 ...循环之外,因为它的值不会改变并且你正在重新计算它。
  2. 每当添加量已超过限制时,请中断循环而不是继续迭代。

答案 1 :(得分:3)

我不知道这是否有用,因为我无法对我即将说的任何内容进行测试,但是......

看起来你应该放置

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,而不是使用列表。我认为将元素添加到集合中应该更快,尽管我没有时间计算这样的事情。

为什么不在add > limit - 即

之后突破n4循环
for n4 in range(0, 22):
   ...
   if (add >= limit):
      break

我认为您只需要在if (add < limit)循环

中进行1 n4次检查
 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