我有一张{integer_key -> list[tuple]}
的地图作为键/值对。元组包含(start,end)
个值,表示子字符串操作的字符串索引。
我的目标是删除重叠区域并返回键/值对为{tuple -> integer_key}
的地图。
映射到较低integer_keys
的范围优先于较高的范围。
下面是我当前实现的可运行示例(需要此ordereddict类):
from collections import OrderedDict
string_length = 20
idx_region_map = OrderedDict()
idx_region_map[0] = [(0,2), (7,10)]
idx_region_map[1] = [(4,5), (18,19)]
idx_region_map[2] = [(3,3), (5,6), (10,13)]
idx_region_map[3] = [(15,17), (19,20)]
# Which can be represented as follows:
#
# |012345678901234567890|
# 0|ooo----oooo----------|
# 1|----oo------------oo-|
# 2|---o-oo---oooo-------|
# 3|---------------ooo-oo|
# ...
def filter_overlaps(string_length, idx_region_map):
region_idx_map = {}
occupied = [False for i in range(string_length)]
for idx, regions in idx_region_map.items():
for region in regions:
start, end = region[0], region[1] + 1
overlaps = any(occupied[start:end])
if not overlaps:
for i in range(start, end):
occupied[i] = True
region_idx_map[region] = idx
return region_idx_map
# Prints: {(3, 3): 2, (4, 5): 1, (18, 19): 1, (7, 10): 0, (0, 2): 0, (15, 17): 3}
print filter_overlaps(string_length, idx_region_map)
这似乎足以满足我的需求,但我很想知道有哪些替代算法可以解决这个问题。例如,使用不同的数据结构或比上述更有效的东西。
答案 0 :(得分:2)
您可以使用Interval tree。
我不懂Python,但我认为你在这里做蛮力。
另一种方法是根据起始索引进行排序;所以对你而言,你得到了
0 3 4 5 7 10 15 18 19
现在浏览每个起始索引,并通过二进制搜索检查其对应的结束索引在起始索引之后的位置,即此处我们取0,得到它的结束索引为2并查看2所在的位置。因为2位于0之后,它不会重叠任何东西,但是让我们说0的结束指数是17然后它意味着0,17重叠所有起始指数直到15,这是3,4,5,7,10,15。复杂性是nlogn。
修改
我刚刚意识到你保留了4,5虽然4,5和5,6重叠,我猜因为4,5整数键是1,它小于5,6的整数键,即2。所以我猜你总是保留较低的整数键,虽然它是重叠的。
如果是这种情况,复杂性将为O(n ^ 2),因为您不能盲目地进行二分查找。对于例如如果4的结束索引是10,那么你将不得不通过5,7和10检查它们的整数键是否小于4。如果它是4,则可以过滤其结束索引,否则保留4。
答案 1 :(得分:0)
而不是occupied = [False]*string_length
您可以维护一个数据结构,该数据结构存储到目前为止看到的非重叠范围并支持.overlaps(start, end)
操作:
def overlaps(self, start, end):
# invariant: all stored intervals do not overlap
# perform binary search on non-overlapping intervals O(log n)
# if overlaps; merge with stored intervals O(m)
# else store (start, end) O(1)
# return whether (start, end) overlaps with already seen intervals
复杂性为O(log n + m)
,其中n
- 存储间隔数,m
- 与给定范围重叠的间隔数。
如果string_length
不大,你的算法就好了。