【问题标题】:java - search sorted list of rectanglesjava - 搜索排序的矩形列表
【发布时间】:2016-01-16 20:07:18
【问题描述】:

我有一个矩形列表,以通常的方式创建:

List<Rectangle> rects = new ArrayList<>();

添加了一些矩形(所有矩形的宽度和高度都非零)。 List 包含的 Rectangles 的数量可以在 0 到 10,000 之间,通常在 4,000 到 6,000 之间。

列表按矩形原点的 X 坐标升序排序,然后对重复的 X 坐标按 Y 坐标升序排序(尽管很少有两个或多个具有相同 X 坐标的矩形)。

我已验证排序正确完成(我正在使用带有自定义比较器的 Collections.sort)。

我需要一个将两个整数 x 和 y 作为输入的方法,并返回找到的第一个包含点 (x,y) 的 Rectangle,如果列表中没有包含该点的 Rectangle,则返回 null。

public Rectangle findContainingRectangle(int x, int y)

提供所需功能的简单方法是遍历列表并在每个 Rectangle 上调用 contains 方法,但这太慢了。

List 将在程序运行时被修改,但与需要搜索 List 的速度相比,这个速度是微不足道的,因此需要相对较慢的初始化的算法是可以的。

我查看了 Collections.binarySearch,但不知道如何使用它。我对 Java 没有太多经验,所以如果有另一个 Collection 可以与 List 类似地使用,但更适合我需要的搜索类型,那就太好了(我已经阅读了有关 Maps 和 Sets 之类的文档,但没有'不承认任何优势)。

【问题讨论】:

  • 这似乎是一个解决方案:stackoverflow.com/questions/10269179/…
  • 谢谢。我的情况有点“简单”,因为我只需要返回一个包含 Rectangle 的内容,但 R-tree 可能仍然是一个解决方案。

标签: java algorithm search 2d sortedlist


【解决方案1】:

在维护排序列表的同时,您可以在“X”坐标上使用二进制搜索来查找包含所需“X”的矩形的候选者,然后在“Y”坐标上使用二进制搜索。

您应该自己实现二进制搜索,我看不到您可以使用 Collections.binarySearch 方法的方法。

预期复杂度:O(log n) 作为 n 矩形的数量。 (有点多,因为你可能有重复)

但是,为此,您应该在添加其他实例的同时保持数组排序,(在每次插入后排序)。

【讨论】:

    【解决方案2】:

    使用HashSetMap 在这里不合适,因为您没有创建键值对,Stream 也不适合这种情况。

    请务必覆盖Rectangle 中的equals()hashCode(),如下所述:Why do I need to override the equals and hashCode methods in Java?

    【讨论】:

      【解决方案3】:

      您可以像这样使用并行流搜索您的列表

      public Rectangle findContainingRectangle(final int x, final int y) {
          List<Rectangle> rectangles = new ArrayList<>();
      
          Rectangle rec = rectangles.parallelStream().filter((r)->{
              if(r.getX()==x && r.getY()==y){
                  return true;
              }
              return false;
          }).findFirst().get();
          return rec;
      }
      

      【讨论】:

        【解决方案4】:

        只需运行多次二进制搜索 - 因为相同 x 的概率很低,正如你所说的,它不会花费很多次,所以它仍然会登录

        a) 运行二分查找

        b) 如果找到则删除项目 - 并将索引保​​留在找到的位置

        c) 在 a) 处对剩余的列表重复二分查找,直到返回 null

        d) 那么你有一个小的索引数组,你可以看到哪个是最小的

        e) 然后在指定位置重新插入删除的元素

        【讨论】:

          【解决方案5】:

          您可以尝试查看流的性能。我不确定它是否足够快,但您可以测试一下。

          Rectangle rec = rects.stream().filter((r)->{
                      return r.contains(x, y);
                  }).findFirst().get();
          

          【讨论】:

            【解决方案6】:

            您可以创建地图。

            Map 是关联两个值的最佳方式。您可以将“x”值与其在列表中的第一个位置相关联。然后你只需要从第一个'x'位置循环到列表中的另一个'x'。

            如果您在地图上没有找到“x”,那么他们的列表中没有合适的矩形。

            通过这种方式,您不会探索所有错误的“x”条目。

            【讨论】:

              猜你喜欢
              • 2014-06-11
              • 1970-01-01
              • 2015-04-23
              • 2011-03-12
              • 2013-03-06
              • 2015-09-26
              • 1970-01-01
              • 1970-01-01
              • 2017-01-19
              相关资源
              最近更新 更多