毕达哥拉斯三倍效率

时间:2014-10-05 17:56:34

标签: python python-2.7

我需要创建一个函数,它接受一个整数列表并返回列表中是否有毕达哥拉斯三元组。例如,[3, 5, 7, 4]返回True,因为3,4,5是毕达哥拉斯三重奏。到目前为止,我有这个(在Python中):

def containsPythagoreanTriple(a): 
    for i in xrange(len(a)): #square the numbers
        num = a[i]
        a[i] = num**2
    a = sorted(a)
    for start in xrange(len(a)): #compare every pair
        for i in xrange(start+1, len(a)):
            if a[start] + a[i] in a:
                return True
    return False

有没有办法让这个更有效率?

2 个答案:

答案 0 :(得分:2)

就性能而言,该代码中有一些可以改进的东西。

当前的实施是O(N**3)(其中Nlen(a)),因为您检查方块列表是否包含每对项目的总和。 list中的成员资格测试为O(N),并且有O(N**2)对要测试。

您可以使用set而不是列表来保存您的项目,从而改善此位。在set中测试项目成员资格为O(1),因此您将以这种方式获得O(N**2)算法。

还有一些进一步的变化可能会加速一些事情,但它们都不会进一步改变渐近复杂性。首先,您无需致电sorted,因为您无论如何都要测试每一对物品。您还可以使用集合理解来进行平方,而不是覆盖原始a列表。最后,您可以使用itertools.combinations生成正方形对,并在生成器表达式上使用any来测试它们的总和是否在集合中。

这是使用相同算法的一些更优化的代码:

import itertools

def containsPythagoreanTriple(a):
    squares = {x*x for x in a} # set comprehension
    return any(x+y in squares for x,y in itertools.combinations(squares))

通过以更基本的方式更改算法,可能还有更多空间来优化事物。例如,您不需要测试每一对,因为某些值永远不会是三角形的“短腿”(例如,最大值)。您可以过滤传递给itertools.combinations的方块,使其仅包含小于或等于max(squares)-min(squares)的方块。我不确定这是否值得,除非你的值列表变得非常大。

答案 1 :(得分:1)

相同,但有点不同

import math    
def tripple(array): 
    array = sorted(array)
    for start in xrange(len(array)): #compare every pair
      m = array[start]
      for i in xrange(start+1, len(array)):
        n = array[i]
        if math.sqrt(n*n+m*m) in array:
          print m, n, math.sqrt(n*n+m*m)

array=[4, 6, 2, 3, 7, 5, 9, 8, 10, 12, 15, 40, 41];     
tripple(array);