假设你有足够的内存,我会使用一个列表数组,其中列表包含包含索引的所有范围。
这是一个更详细地展示算法的 Python 解决方案:
# (Inclusive) ranges
ranges = [(0,500), (0,100), (75,127), (125,157), (130,198), (198,200)]
smallest = min(r[0] for r in ranges)
largest = max(r[1] for r in ranges)
# Ceate table
table = [[] for i in range(smallest, largest+1)] # List of lists
for r in ranges: # pre-compute results
mn, mx = r
for index in range(mn, mx+1):
table[index - smallest].append(r)
def check(n):
'Return list of ranges containing n'
if smallest <= n <= largest:
return table[n - smallest]
else:
return [] # Out of range
for n in [-10, 10, 75, 127, 129, 130, 158, 197, 198, 199, 500, 501]:
print('%3i is in groups: %r' % (n, check(n)))
输出是:
-10 is in groups: []
10 is in groups: [(0, 500), (0, 100)]
75 is in groups: [(0, 500), (0, 100), (75, 127)]
127 is in groups: [(0, 500), (75, 127), (125, 157)]
129 is in groups: [(0, 500), (125, 157)]
130 is in groups: [(0, 500), (125, 157), (130, 198)]
158 is in groups: [(0, 500), (130, 198)]
197 is in groups: [(0, 500), (130, 198)]
198 is in groups: [(0, 500), (130, 198), (198, 200)]
199 is in groups: [(0, 500), (198, 200)]
500 is in groups: [(0, 500)]
501 is in groups: []
可以进行进一步优化,例如使用位集来存储每个索引处的范围而不是列表。
从下面的 cmets 中,我决定修改上面的方法,在上面的表查找方法和基于直接比较的较慢但内存效率更高的解决方案之间进行选择。 (理想情况下也会包含一个基于区间树的解决方案):
# (Inclusive) ranges
ranges = [(0,500), (0,100), (75,127), (125,157), (130,198), (198,200)]
limit = 1000000 # Or whatever
smallest = min(r[0] for r in ranges)
largest = max(r[1] for r in ranges)
if (largest - smallest) * len(ranges) < limit:
# Ceate table
table = [[] for i in range(smallest, largest+1)] # List of lists
for r in ranges:
mn, mx = r
for index in range(mn, mx+1):
table[index - smallest].append(r)
def check(n):
'Return list of ranges containing n'
if smallest <= n <= largest:
return table[n - smallest]
else:
return [] # Out of range
else:
# mpre emory efficient method, for example
def check(n):
return [(mn, mx) for mn, mx in ranges if mn <= n <= mx]
for n in [-10, 10, 75, 127, 129, 130, 158, 197, 198, 199, 500, 501]:
print('%3i is in groups: %r' % (n, check(n)))