如何从给定数字的连续范围集中查找范围

时间:2014-07-28 20:40:53

标签: java math lookup integer-hashing

如此简单地说,这就是我想要做的事情:

我有一组Range个连续的对象(非重叠,它们之间没有间隙),每个对象包含一个startend int,以及一个对另一个对象的引用obj。这些范围不是固定大小(第一个可能是1-49,第二个是50-221等)。这个系列可能会变得非常大。

我希望找到一种方法来查找包含给定数字的范围(或更具体地说,它引用的对象),而不必遍历整个集合,检查每个范围以查看它是否包含该数字。这些查找将经常执行,因此速度/性能是关键。

有谁知道可能会帮助我的算法/等式?我是用Java写的。如果需要,我可以提供更多细节,但我想我会尽量保持简单。

感谢。

3 个答案:

答案 0 :(得分:4)

如果您想要使用TreeMap,其中键是范围的底部,而值是Range对象。

然后要确定正确的范围,只需使用floorEntry()方法快速获取最接近(较小或相等)Range,其中应包含密钥,如下所示:

    TreeMap<Integer, Range> map = new TreeMap<>();
    map.put(1, new Range(1, 10));
    map.put(11, new Range(11, 30));
    map.put(31, new Range(31, 100));

    // int key = 0; // null
    // int key = 1; // Range [start=1, end=10]
    // int key = 11; // Range [start=11, end=30]
    // int key = 21; // Range [start=11, end=30]
    // int key = 31; // Range [start=31, end=100]
    // int key = 41; // Range [start=31, end=100]
    int key = 101; // Range [start=31, end=100]
    // etc.

    Range r = null;
    Map.Entry<Integer, Range> m = map.floorEntry(key);
    if (m != null) {
        r = m.getValue();
    }
    System.out.println(r);

由于树总是按照底部范围边界的自然顺序排序,因此所有搜索都将处于最差O(log(n))。

您希望在密钥完全超出范围时添加一些健全性检查(例如,当密钥超出地图的末尾时,它会返回地图中的最后一个Range ),但这应该让你知道如何继续。

答案 1 :(得分:1)

假设您查找是最重要的,并且您可以节省O(N)内存和大约O(N ^ 2)预处理时间,算法将是:

  • 介绍一个班级ObjectsInRange,其中包含:范围的开头(int startOfRange)和一组对象(Set<Object> objects
  • 引入ArrayList<ObjectsInRange> oir,其中包含按ObjectsInRange
  • 排序的startOfRange
  • 对于每个Range r,确保存在ObjectsInRange(让我们称之为ab),a.startOfRange = r.startb.startOfRange = b.end。然后,对于ObjectsInRange x之间的所有a,以及直到(但不包括)br.obj添加x.objects

然后,查找如下:

  • 对于整数x,找到ioir[i].startOfRange <= x
  • 这样的oir[i+1].startOfRange > x
  • 注意:可以在O(log N)时间内找到二分的i
  • 您的对象为oir[i].objects

答案 2 :(得分:0)

如果集合是有序的,那么您可以实现二进制搜索以在O(log(n))时间内找到正确的范围。对于非常大的集合,它不如散列效率高,但如果你的范围小于1000,它可能会更快(因为它更简单)。