【问题标题】:Finding all the Pythagorean quadruples faster when a, b or c <= 1000当 a、b 或 c <= 1000 时,更快地找到所有毕达哥拉斯四元组
【发布时间】:2020-02-20 16:35:11
【问题描述】:

我正在尝试得到所有的毕达哥拉斯四元组:

a^2 + b^2 + c^2 = d^2 when a, b, c &lt;= 1000,

我的代码生成了所有这些 (85490),但大约需要 10 分钟

我正在尝试减少执行时间。如何提高执行时间?请有任何建议。

这是我的代码。

   static int isSquare(int n)
   {
      int m = (int) Math.sqrt(n);

      return m * m == n ? m : 0;
   }

   static List<List<Integer>> allQuadraples = new ArrayList<>();

   static int findQuadraples(int range)
   {
      int total = 0;

      for (int a = 1; a <= range; a++)
         for (int b = 1; b <= range; b++)
            for (int c = 1; c <= range; c++)
            {
               int sum = a * a + b * b + c * c;

               int d = isSquare(sum);

               if (d != 0) // a possible Quadruple
               {
                  List<Integer> oneQuadraple = new ArrayList<>(Arrays.asList(a, b, c, d));
                  Collections.sort(oneQuadraple); // sorting before insertion for comparing later
                  if (!allQuadraples.contains(oneQuadraple))
                  {
                     System.out.println(oneQuadraple);
                     allQuadraples.add(oneQuadraple);
                     total++;
                  }
               }
            }

      return total;
   }

【问题讨论】:

  • 请注意,在不更改这种蛮力方法的情况下,您可以通过以下方式获得时间:1. 限制搜索 b&gt;=ac&gt;= b 以及 2. 分解计算 a*a 和 @987654328 @
  • 1.您不想每次都调用 sqrt。您可以创建正方形及其根的地图。 2. 你应该重写你的循环使用(除了上面提到的假设a&lt;b&lt;c)这些是三角形,所以:a+b&gt;c &amp;&amp; a+c&gt;b &amp;&amp; b+c&gt;a
  • 我在 C++ 中测试了我的两个提案,并在大约 1 秒内得到了与您相同的结果,但基本还是蛮力方法,但不需要检查重复项
  • @ManojBanik 在b&gt;=ac&gt;= b 的条件下,我避免了所有重复。我得到与 OP 相同的总数:85490

标签: java algorithm time-complexity pythagorean


【解决方案1】:

所以,如果您仍然需要存储所有四元组,那么这是新功能, (感谢达米恩)。

只用了 1.5 秒。用于查找和存储所有 85490

   static int findQuadraples(int range)
   {
      int total = 0;

      for (int a = 1; a <= range; a++)
         for (int b = a; b <= range; b++)
            for (int c = b; c <= range; c++)
            {
               int sum = a * a + b * b + c * c;
               int d = isSquare(sum);

               if (d != 0) // a possible Quadruple
               {
                  //System.out.println(Arrays.asList(a, b, c, d));
                  allQuadraples.add(Arrays.asList(a, b, c, d));
                  total++;
               }
            }

      return total;
   }

如果不保存到 ArrayList,则需要 1.3 秒

【讨论】:

  • 注意:我还测试了限制与 int a2=a*a 等的乘法次数,但在 C++ 中增益可以忽略不计。也许要在java中进行测试。您还可以在帖子中提到,主要优点是避免搜索重复项 (+1)
  • 您可以将 new ArrayList&lt;&gt;(Arrays.asList(Arrays.asList(a, b, c, d)) 更改为 Arrays.asList(a, b, c, d)。这是一个不可变的列表,但无论如何您都不会更改它们;)
  • @vicpermir,是的,它需要更少的时间。更新了我的答案。
  • 糟糕,好像我在评论中粘贴了两次Arrays.asList(,但你明白了,呵呵
【解决方案2】:

这是一种使用较慢语言的不同方法。将a^2 + b^2d^2 - c^2 匹配。操作速度较慢,但​​算法是O(n^2) 而不是O(n^3)

在 Python 中,这在我的笔记本电脑上花费了

#! /usr/bin/env python3
limit = 1000

square_differences = {}
for c in range(limit, 0, -1):
    for d in range (c+1, 2*c):
        diff = d*d - c*c
        if 3*limit*limit< diff:
            break
        elif diff not in square_differences:
            square_differences[diff] = []
        square_differences[diff].append((c, d))

quads = []
for a in range(1, limit+1):
    for b in range(a, limit+1):
        s = a*a + b*b
        if s in square_differences:
            for c, d in square_differences[s]:
                if c < b:
                    break
                else:
                    quads.append((a, b, c, d))

print(len(quads))

【讨论】:

  • 您的代码是否生成所有四元组?因为,在某些情况下,不同的“d^2 - c^2”会产生相同的答案,而您没有通过“diff not in square_differences”语句存储所有答案。我在尝试用 Java 转换你的想法时发现了它。
  • @ManojBanik 它生成所有四倍体。诀窍是我强迫a &lt;= b &lt;= c &lt;= d。所以如果d &gt;= 2c 那么a^2 + b^2 + c^2 &lt;= 3c^2 &lt; 4c^2 = (2c)^2 &lt;= d^2。中间的不等式就是为什么我只需要在c &lt; d &lt; 2c 时存储d^2-c^2。我还通过降序c 存储任何特定输出的答案。这让我在c &lt; b 之后不再查看列表的其余部分。
  • 终于我能够在Java 中实现您的O(n^2) 想法,是的,它比我之前的更快,因为1000 它需要0.7 sec。与1.3 相比,2000 需要3.1 sec。与 9.9 相比,3000 需要 10.1 sec。与33.9相比。
猜你喜欢
  • 2011-02-18
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多