java - 搜索矩形的排序列表

时间:2016-01-16 20:07:19

标签: java algorithm search 2d sortedlist

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

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

添加了一些矩形(所有矩形都具有非零宽度和高度)。列表包含的矩形数可以是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方法,但这太慢了。

列表将在程序运行时被修改,但与列表需要搜索的速率相比,其速率微不足道,因此需要相对较慢初始化的算法很好。

我查看了Collections.binarySearch,但无法弄清楚它是如何使用的。我没有多少Java经验,所以如果有另一个可以类似于List使用的Collection,但更适合我需要的搜索类型,那就太棒了(我读过了)关于诸如地图和集合之类的文档,但没有认识到任何优势)。

6 个答案:

答案 0 :(得分:2)

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

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

预期的复杂性:O(log n)为n的矩形数。 (它可能会有更多重复)

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

答案 1 :(得分:1)

使用HashSetMap此处不合适,因为您未创建键值对,Stream也不适合此上下文。

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

答案 2 :(得分:1)

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

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;
}

答案 3 :(得分:1)

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

a)运行二进制搜索

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

c)在a)用剩余的列表重复二进制搜索,直到返回null

d)然后你有一小部分索引,你可以看到哪一个是最小的

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

答案 4 :(得分:0)

您可以创建地图。

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

如果您在地图上找不到“x”,则列表上没有好的矩形。

通过这种方式,你不会探索所有糟糕的'x'条目。

答案 5 :(得分:0)

您可以尝试查看流的效果。我不确定它是否足够快但你可以测试它。

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