我需要创建一个函数,它接受一个整数列表并返回列表中是否有毕达哥拉斯三元组。例如,[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
有没有办法让这个更有效率?
答案 0 :(得分:2)
就性能而言,该代码中有一些可以改进的东西。
当前的实施是O(N**3)
(其中N
是len(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);