Dynamic range search [duplicate]

半城伤御伤魂 提交于 2019-12-08 08:00:02

问题


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?


回答1:


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".



来源:https://stackoverflow.com/questions/8262606/dynamic-range-search

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!