Java Program to Find Pythagorean Triplets in an Array

2025 年 3 月 28 日 | 阅读 10 分钟

勾股数是一个由三个正整数 (a, b, c) 组成的集合,它们满足以下方程

在这个方程中,'c' 是最大的数,代表直角三角形的斜边,而 'a' 和 'b' 是另外两条边。例如,集合 (3, 4, 5) 构成一个勾股数,因为当你将 3 和 4 的平方相加时 (3² + 4²),你得到 5 的平方 (即 9 + 16 = 25)。

示例 1

输入

输出

 
False   

朴素方法

代码中使用的朴素方法涉及三个 嵌套循环 来检查数组中每个可能的三个元素组合,并检查它们的平方是否满足 勾股定理。这种方法虽然直接,但由于其立方时间复杂度,对于大型数组效率低下。

算法

步骤 1: 遍历数组并对每个元素进行平方。

步骤 2: 将平方后的值按非递减顺序排列。

步骤 3: 从排序数组中的最大元素开始向后迭代。

步骤 4: 将当前元素视为斜边,并使用双指针方法检查数组中的另外两个元素是否加起来等于该值。

步骤 5: 如果找到一个勾股数,则返回 true。如果经过所有检查后没有找到勾股数,则返回 false。

实施

文件名:PythagoreanTripletChecker.java

输出

 
Yes   

时间复杂度: 由于三个嵌套循环,时间复杂度为 O(n^3)。

辅助空间复杂度: 辅助空间复杂度为 O(1),因为只使用了少数几个额外的 变量

使用排序方法

“使用排序”方法涉及对数组进行排序,使元素按可预测的顺序排列,从而简化了问题。通过将双指针方法等技术应用于排序后的 数组,可以有效地检查诸如勾股数之类的条件。

算法

步骤 1: 遍历数组并将每个元素转换为其平方值。

步骤 2: 将这些平方值按升序排列。

步骤 3: 对于每个元素(潜在的斜边),使用双指针技术

  • 初始化两个指针:一个指向数组的开头,另一个指向当前元素的前一个位置。
  • 检查两个指针处值的和是否等于当前元素。

步骤 4: 根据和的比较调整指针

  • 如果和小于当前元素,则将左 指针 向右移动。
  • 如果和大于当前元素,则将右指针向左移动。

步骤 5: 如果发现一个满足勾股定理的有效勾股数,则返回 true。如果在检查了所有组合后没有找到这样的勾股数,则返回 false。

实施

文件名:TripletChecker.java

输出

 
Yes   

时间复杂度: O(n^2) 主要由双指针搜索勾股数决定。

辅助空间: O(1) 除输入数组和指针外,没有额外的空间。

方法:使用哈希

哈希可以加快查找勾股数的过程,通过使用频率数组来快速检查潜在的勾股数元素是否存在。该方法最大限度地减少了对嵌套循环和重复比较的需求。

算法

步骤 1: 确定数组中的最大值,以确定频率数组所需的尺寸。

步骤 2: 构建一个频率数组,其中每个索引对应一个数字,并保存该数字在原始数组中的计数。

步骤 3: 对于频率数组中的每个潜在值,仅当该值存在时才继续。

步骤 4: 对于 b 的每个可能值,如果 b 不存在或 a 和 b 相同但 a 只出现一次,则跳过。

步骤 5: 将 c 计算为 a^2 + b^2 的平方根,并检查 c 是否存在于频率数组中并满足勾股条件。如果找到一个有效的勾股数,则返回 true;否则,在所有检查完成后返回 false。

实施

文件名:TripletFinder.java

输出

 
Yes   

时间复杂度: O(n²),其中 n 是数组中的元素数量。这是由于用于查找有效勾股数的嵌套循环。

辅助空间复杂度: O(n),用于管理数组的频率映射。

方法:暴力法结合哈希表优化

代码使用一种暴力方法来检查每对元素以找到勾股数。为了提高效率,它利用 HashMap,该方法可以快速验证潜在的斜边是否存在于勾股数中。

算法

步骤 1: 初始化一个 HashMap 来记录数组中每个数字的频率。

步骤 2: 遍历数组,用每个数字的计数更新 HashMap。

步骤 3: 对于数组中的每一对元素,使用勾股关系计算潜在的斜边。

步骤 4: 检查计算出的斜边是否存在于 HashMap 中,并确保其平方等于两个元素的平方和。

步骤 5: 如果在此过程中找到了有效的勾股数,则返回 true。如果在检查所有组合后未发现此类勾股数,则返回 false。

实施

文件名: TripletDetector.java

输出

 
Yes   

时间复杂度: O(n^2),由于嵌套循环检查元素对。

空间复杂度: O(n),用于存储元素频率的 HashMap。

方法:使用排序和哈希集

排序和哈希集方法首先对数组的平方值进行排序,以便于系统地检查勾股数。然后,它使用 HashSet 来有效地检查当前平方值与任何先前遇到的平方值的差值是否构成有效的勾股数。

算法

步骤 1: 计算数组中每个元素的平方,并将这些平方值按升序排序。

步骤 2: 从排序列表的末尾开始,将每个值视为潜在的斜边。

步骤 3: 使用 HashSet 来记住先前遇到的平方值,并确定对于每个潜在的斜边是否可以形成一个有效的勾股数。

步骤 4: 如果找到一个有效的勾股数,则返回 true;否则,在检查完所有可能性后返回 false。

实施

文件名:TripletFinder.java

输出

 
Yes   

时间复杂度: O(n^2),由于嵌套循环检查元素对。

辅助空间复杂度: O(n),用于跟踪已见平方值的 HashSet。