【问题标题】:How to find if a point is within a set of intervals?如何查找一个点是否在一组区间内?
【发布时间】:2012-04-12 19:49:36
【问题描述】:

我正在寻找最快的方法来确定一条线上的点是否在这条线的子集内。 我得到一个整数点,我也有一个“列表”:

  1. 点,用整数表示(3、10、1000 等)
  2. 间隔,我用 2 个整数表示(2:10 是从 2 到 10 的所有整数,包括 50:60 等)

在这个例子中,如果我的点的值为 5,那么我返回 true,因为它包含在一个区间中,对于 55 也是如此。如果我的点等于 1000,我也返回 true,因为它与列表匹配点。

我正在寻找一种快速的方法(比线性更快)来检查这种情况,而不必实例化尽可能多的整数(即,对于 1:1000 的间隔,我不想实例化 1000整数)。 这可以在对数时间内完成吗?

谢谢

编辑: 您可以认为预处理数据列表所花费的任何时间都等于 0,因为一旦处理了我的初始间隔,我需要将此测试应用于 10k 点

【问题讨论】:

  • 间隔可以重叠吗?我不确定这是否重要,但感觉应该如此。
  • 他们可以,但我可以预处理我的数据,以便它们不再存在,这在时间上没有问题,因为我使用相同的间隔集来处理 10k 点
  • 你需要知道一个点在哪些区间,或者仅仅知道它是否在其中吗?
  • 澄清一下,这个“列表”可能看起来像这样? (3, 2:10, 10, 50:60, 1000) 另外,如果有一个有趣的问题,请 +1。
  • @Karl Bielefeldt:我只返回一个布尔值

标签: c++ c algorithm computational-geometry


【解决方案1】:

经过反思,我认为以下代码应该在对数时间内工作,不包括构建地图所需的时间:

enum pointType {
    point,
    open,
    close
};
std::map<long int, pointType> mapPoints;

mapPoints.insert(std::pair<long int, pointType>(3, point));

//create the 5:10 interval:
mapPoints.insert(std::pair<long int, pointType>(5, open));
mapPoints.insert(std::pair<long int, pointType>(10, close));

int number = 4;
bool inside = false;
std::map<long int, pointType>::iterator it1 = mapPoints.lower_bound(number);

if(it1->first == number || it1->second == close) {
    inside = true;
}

我认为只要地图以非重叠间隔正确填充,这应该可以工作

【讨论】:

    【解决方案2】:

    【讨论】:

    • +1 为正确答案。这是一个经过充分研究的计算几何问题(“1D stabbing query”)。
    【解决方案3】:

    如果您对整数范围进行了排序并且范围不重叠,则可以执行二进制搜索以在对数时间内找到正确的范围。

    范围有什么限制吗?基于此,您可能会想出散列函数来在恒定时间内进行搜索。但这取决于您的约束条件。

    【讨论】:

    • 我想我可以假设范围在 0 到 1000 万之间。
    • 如果某些范围重叠,您可以对它们进行排序并将重叠的范围折叠成一个范围。
    【解决方案4】:

    首先检查点的 hash_map。这就是简单的检查。

    然后只需按第一个坐标对区间图进行排序,然后找到该点的 lower_bound。

    然后检查你是否包含在返回的元素中。如果你不在那个,你就不在其中。

    【讨论】:

    • 在一些响应中似乎存在间隔可能重叠的假设。您可以控制用于解决此问题的数据结构 - 它不需要外部或初始间隔集。因此,您通常不应该存储重叠间隔 - 在插入地图时加入它们。每当处理间隔时,这是相当标准的。
    【解决方案5】:

    如果您不计算构建树所需的时间(大多数树需要 n log n 或类似时间构建)。

    如果你只有一个简单的列表,那么你不能做得比线性更好,因为在最坏的情况下你可能必须检查所有点和间隔。

    【讨论】:

      【解决方案6】:

      您可以使用Bloom Filter 来测试一个点,看看它是否在一个区间内不是,在线性 O(1) 时间内。如果它通过了该测试,您必须使用另一种方法,例如二进制搜索,以查看它是否确实是间隔的一部分,在 O(log n) 时间内。

      【讨论】:

      • @MatthiasVallentin,是的。布隆过滤器的大小取决于设置的点数和误报的概率,而不是可能的输入范围。
      • 谢谢,我现在明白你的想法了。但是,最初需要修复的布隆过滤器参数有很多选择。由于这种数据结构通常用于空间受限的环境中,因此一种常见的方法是假设固定大小并设置基数来导出 k 的最佳值,即散列函数的数量。你能澄清一下“大小”是什么意思吗?一旦实例化,(基本)布隆过滤器的大小通常不会再改变。
      • @MatthiasVallentin,抱歉我不清楚。我的意思是,一旦选择了点数和误报概率(以及散列函数的数量),就可以计算过滤器数组的大小。关键是它取决于输入的范围。
      猜你喜欢
      • 1970-01-01
      • 2018-04-30
      • 1970-01-01
      • 2022-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      相关资源
      最近更新 更多