动态范围搜索

发布于 2024-12-18 02:11:27 字数 618 浏览 5 评论 0原文

可能的重复:
快速算法快速找到一组范围中某个数字所属的范围?

给定一个不重叠且已排序的数字范围列表(rangeList)和一个数字,编写一个有效的算法,首先查找该数字是否存在于 rangeList(某个范围)中,如果存在,则返回正确的范围。

例如 rangeList = [(-1, 200), (300, 2000), (2011, 2300)]

查询 1: 1000 -> (True, (300, 2000) ),因为 1000 位于 300 和 2000 之间。

查询 2:250 -> (False, (None, None) ) 因为 no 250 不存在于列表中的任何范围内。

我想出的最好的算法是使用二分搜索的 log N。这感觉像是一个非常常见的问题,特别是对于基于经度/纬度的搜索。有什么想法可以让它比 log N 更好吗?

Possible Duplicate:
Fast Algorithm to Quickly Find the Range a Number Belongs to in a Set of Ranges?

Given a list of range of numbers that are non-overlapping and sorted (rangeList), and a number, write an efficient algorithm to find first whether this number exists in (some range in) rangeList and if it does exist, return the correct range.

For example rangeList = [(-1, 200), (300, 2000), (2011, 2300)]

Query 1: 1000 -> (True, (300, 2000) ) since 1000 lies between 300 and 2000.

Query 2: 250 -> (False, (None, None) ) since no 250 does not exist in any range in the list.

The best algorithm I have come up with is log N using binary search. This feels like a very common problem especially for Longitude/Latitude based searches. Any ideas to make this better than log N?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

千仐 2024-12-25 02:11:27

我不确定这是否会实现你想要的,但这是一个尝试。它将涉及 O(n) 预处理步骤,并且作为回报,将为任何给定查询提供 O(1) 运行时间(通过参数 c)平衡空间复杂度的机会。如果您的 rangeList 经常更改,这可能没有帮助。

预处理步骤:

  1. 查找范围列表的“总范围”(可接受的最低值和最高值,尽管之间会有间隙)。 O(1)

  2. 选择一个浓度参数 c(整数)来表示您想要在该范围内评估的点数。 O(1)

  3. 创建一个映射函数,将整数 [1, c] 映射到步骤 1 中找到的总范围,并且还可以执行逆操作(这并不比摄氏度 - 华氏度转换更复杂)。还可以 O(1)

  4. 利用映射函数,确定总范围内与[1, c]对应的点。扫描范围列表,随时评估这些点,将答案((True, (300, 2000)) 等)存储在长度为 c 的数组中(我们将数组称为“Evaluated”)。 O(n + c)

收到查询后:

  1. 使用映射函数将查询数转换为“总范围”->O(n + c) [1,c]方向。如果转换后的数字超出范围 [1, c],则返回 (False, None, None)。 O(1)

  2. 取转换后数字的上限和下限,这将得到两个整数 a 和 b。比较已评估的[a] 和已评估的[b]。如果它们包含相同的答案,则返回它(如果您转换后的数字已经是整数,则直接返回 Evaluated[converted number])。 O(1)

  3. 如果 Evaluated[a] 和 Evaluated[b] 给出不同的答案,则必须进行二分查找。但您至少可以在 a 和 b 之间的中间开始搜索,映射回“总范围”。

I'm not sure this will accomplish what you want, but it's a shot. It would involve an O(n) preprocessing step, and in return would offer a chance at O(1) runtime for any given query balanced against space complexity (via the parameter c). If your rangeList changes frequently, this will probably not be helpful.

Preprocessing steps:

  1. Find the "total range" of the list of ranges (lowest acceptable value and highest, though there will be gaps in between). O(1)

  2. Select a concentration parameter c (integer) for how many points you'd like to evaluate in that range. O(1)

  3. Create a mapping function that maps integers [1, c] to the total range found in step 1, and can also do the inverse (this is no more complicated than a Celsius-Farenheit conversion). also O(1)

  4. Using the mapping function, determine the points in the total range that correspond to [1, c]. Scan through the list of ranges, evaluating these points as you go, storing the answers ( (True, (300, 2000)), etc.) in an array of length c (let's call the array "Evaluated"). O(n + c)

Upon receiving a query:

  1. Use the mapping function to convert the query number in the "total range" -> [1, c] direction. If the converted number falls outside the range [1, c], return (False, None, None). O(1)

  2. Take the ceiling and floor of the converted number, which will give you two integers a and b. Compare Evaluated[a] and Evaluated[b]. If they contain the same answer, return it (if your converted number was already an integer, return Evaluated[converted number] directly). O(1)

  3. If Evaluated[a] and Evaluated[b] give different answers, you have to do a binary search. But you can at least start the search at halfway between a and b, mapped back into "total range".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文