使用python查找列表中的勾股三元组数目?

时间:2018-10-17 07:40:11

标签: python computer-science pythagorean

我正在编码一个问题的解决方案,其中代码将在给定列表a的情况下找到列表中的勾股三元组的数量。但是,当我将代码提交给自动分级机时,有一些测试案例使我的代码失败,但是我不知道出了什么问题。请帮助我指出我的错误.....

def Q3(a):
    lst = [i ** 2 for i in a]
    lst.sort()
    ans = 0

    for x in lst:
        for y in lst:
            if (x + y) in lst:
                ans += 1

    return ans // 2

“毕达哥拉斯三元组”是毕达哥拉斯定理的整数解,例如32 + 42 = 52。给定正整数列表,找到勾股三胞胎的数量。如果至少一个整数不同,则两个毕达哥拉斯三胞胎也将不同。

实施

·实现函数Q3(A),其中A是一个正整数列表。列表A的大小最大为250。

·列表A中没有重复项

·此函数返回勾股三胞胎的数量。

样品

·Q3([3,4,6,5])= 1

·Q3([4,5,6])= 0

3 个答案:

答案 0 :(得分:1)

简单但不是非常有效的解决方案是在 3 个嵌套的 for 循环中循环遍历范围内的数字列表(例如,我取了 1 到 100 的数字),如下所示。但是对于100个元素会比较慢,需要100^3次操作

triplets = []
for base in range(1,101):
    for height in range(1,101):
        for hypotenuse in range(1,101):
            # check if forms a triplet

            if hypotenuse**2 == base**2 + height**2:
                triplets.append(base, height, hypotenuse)

这可以稍微提高效率(有更好的解决方案) 通过计算每个底和高组合的斜边,然后检查斜边是否为整数

    triplets = []
    for base in range(1,101):
        for height in range(1,101):
            hypotenuse = math.sqrt(base**2 + height**2)
            # check if hypotenuse is integer by ramiander division by 1                    
            if hypotenuse%1==0:
                triplets.append(base, height, hypotenuse)  
                 

# the above solution written a list comprehension
a = range(1,101)
[(i,j,math.sqrt(i*i+j*j)) for i in a for j in a if math.sqrt(i*i+j*j)%1==0]

如果您认为 (3,4,5) 和 (3,5,4) 不同,请使用集合而不是列表并最终获得 len(triplets_set)

答案 1 :(得分:-1)

问题1:假设您输入的是

[3,4,5,5,5]

尽管您的问题尚不清楚,但我的推测是这应该算作3个毕达哥拉斯三元组,每个都使用这3个5s中的一个。

您的函数只会返回1。

问题2:正如Sayse指出的那样,您的“三胞胎”可能试图两次使用相同的数字。

最好使用itertools.combinations从正方形列表中获得不同的组合,并计算出现多少合适的三元组。

from itertools import combinations

def Q3(a):
    squares = [i**2 for i in a]
    squares.sort()
    ans = 0

    for x,y,z in combinations(squares, 3):
        if x + y == z:
            ans += 1

    return ans

答案 2 :(得分:-1)

鉴于您现在通过编辑添加到问题中的输入约束,我认为您的实现在逻辑上没有任何问题。您的代码无法通过的唯一测试用例类型必须与性能相关,因为您正在使用最慢的解决方案之一,方法是使用3个嵌套循环在列表的整个范围内进行迭代(in运算符本身是通过循环实现的。

由于列表已排序并且我们想要x < y < z,因此我们应使yx + 1开始,并使zy + 1开始。并且由于给定了x,所以x的值取决于y的值,对于每个给定的y,我们可以递增z直到{{1} }不再成立,如果此时z * z < x * x + y * y,我们已经找到了毕达哥拉斯三元组。这允许z * z == x * x + y * yy仅扫过z之上的值一次,因此将时间复杂度从O(n ^ 3)降低到O(n ^ 2),从而使时间变得复杂列表大小为250时快40倍:

x