【问题标题】:How to find if a number is contained in an array of number ranges in java如何查找一个数字是否包含在java中的数字范围数组中
【发布时间】:2010-11-07 08:47:49
【问题描述】:

我有一个 java 对象数组。

  • 每个对象存储两个定义数字范围的长整数。
  • 我已经保证,对于范围内的所有对象,数字范围不会重叠。

我想快速找到数组中的特定对象,给定一个可能(或可能不)在对象定义的数字范围之一内的数字。

我希望使用 Array.binarySearch 来执行此操作,但这看起来不合适。

您有什么想法可以做到这一点吗?

【问题讨论】:

  • 数组是否以任何方式排序?
  • Array.binarySearch 要求您的数组提前排序。是吗?
  • 不,它没有排序。对数组进行排序似乎很容易,但是由于我试图找到一个范围内的数字,所以二进制搜索更难。

标签: java arrays search


【解决方案1】:

如果 a.start > b.end,让数组中的项实现 Comparable 接口,让项 a 大于另一个项 b。然后使用此比较对数组进行排序。

然后要查找数字 x 是否在数组中某个项目的范围内,请在数组中搜索 k.end >= x 的第一个项目 k,并检查 k.start

【讨论】:

  • 我肯定会这样做。我什至可能会先对数组进行排序,然后对值进行二进制搜索。
  • 这通常不是一个完整的排序。因此,我会选择 Comparator。实际上,我还是更喜欢 Comparator。
  • 我不确定我是否理解这一点。如何使用 k.end >= 在数组中搜索第一项 k ?
  • 例如通过循环遍历数组,当你找到它时会中断?或者通过从该数组的中间开始,向左或向右等应用一些二进制搜索
  • 我不想对数组进行线性搜索——这正是我想要避免的。我也希望避免实现我自己的 binarySearch()。我认为可能有某种方法可以让现有的方法服从我的意愿。
【解决方案2】:

使用 TreeMap。关键是两个 Long range 界限中的较低者;值就是对象。

private TreeMap<Long, T> map = new TreeMap<Long, T>();

void insertObject(T object) {
    map.put(object, object.getLowerRangeBoundary());
}

T getObjectByKeyInRange(Long query) {
    // Get the first Object in the tree that corresponds with the query
    Map.Entry<Long, T> e = map.floorEntry(query);

    // If there's no entry, then the query value is lower than all ranges in the tree
    if (e == null) {
        return null;
    }

    T target = e.getValue();
    // "target" is the only object that can contain the query value
    // If the query value is within the range of "target", then it is our object
    if (query < target.getUpperRangeBoundary()) {
        return target;
    }

    // Nobody has the query value in their range; return null
    return null;
}

【讨论】:

    【解决方案3】:

    您实际上可以非常有效地处理这个问题(对于大量范围和对范围的数百万个查询)并且允许范围重叠。

    伪代码:

    设 rangeMap 为 TreeMap:

    foreach(Range r in ranges)
        rangeMap[r.start].Increment();
        rangeMap[r.end].Decrement();
    

    rangeMap.GreatestLowerBound(i) 现在将返回给定整数 i 所属的范围数(即 GreatestLowerBound 是最大数

    如果您预先知道范围的数量,您可以在实际性能方面做得更好...通过分配单个数组,用“deltaRange”填充它,然后“集成”以获得显示累积的数组“范围”为每个数字 x。

    【讨论】:

      猜你喜欢
      • 2010-12-09
      • 1970-01-01
      • 2014-12-05
      • 1970-01-01
      • 2014-03-01
      • 2020-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多