首先我从你的例子中假设(0,1)
和(1,2)
重叠。
顺便说一句,你的例子是不正确,(3,7)
不(0,2)
一种方式重叠解决是这样的:
- 排序根据起点
- 从最低起点迭代间隔到最高点
2a。计算比当前起始点更大的以前端点数量或等于。
2b。添加一个到当前终点的数量。
步骤1在O(n log n)
第2步是遍历所有的时间间隔,而这样做的计数来完成。所以这是O(n * X)
其中X
是做计数的复杂性。用Fenwick Tree,我们可以在O(log n)
这样做,所以第2步也可以在O(n log n)
内完成。
所以整体复杂度是O(n log n)
。
伪代码:
def fenwick_tree.get(num):
return the sum from counter[0] to counter[num]
def fenwick_tree.add(num, val):
add one to counter[num]
intervals = [...]
sort(intervals) # using the starting point as the key
init_fenwick_tree()
sum = 0
count = 0
for (starting_point, end_point) in intervals:
sum = sum + (count - fenwick_tree.get(starting_point-1))
fenwick_tree.add(end_point,1)
return sum
Python代码(仅当间隔点是一个非负整数作品):
MAX_VALUE = 2**20-1
f_arr = [0]*MAX_VALUE
def reset():
global f_arr, MAX_VALUE
f_arr[:] = [0]*MAX_VALUE
def update(idx,val):
global f_arr
while idx<MAX_VALUE:
f_arr[idx]+=val
idx += (idx & -idx)
def read(idx):
global f_arr
if idx <= 0:
return 0
result = 0
while idx > 0:
result += f_arr[idx]
idx -= (idx & -idx)
return result
intervals = [(1,4),(3,7),(5,8),(14,17),(0,2),(11,14)]
intervals = sorted(intervals, key=lambda x: x[0])
reset()
total = 0
for processed, interval in enumerate(intervals):
(start, end) = interval
total += processed - read(start-1)
update(end, 1)
print total
将打印4
,它来源于这些重叠:
(0,2) - (1,4)
(1,4) - (3,7)
(3,7) - (5,8)
(11,14) - (14,17)
请注意,我们无法获得重叠间隔,因为在最坏的情况下,重新将O(n^2)
重叠,这在O(n log n)
时间内无法打印。
实际上树状数组确实计数在O(log M)
时间,其中M
在区间不同值的最大可能的数目。请注意0,因为只能有很多不同的值。所以说Fenwick Tree在O(log n)
时间内进行计数也是正确的。
这与[间隔树](http://en.wikipedia.org/wiki/Interval_tree) – qxixp
有关 - 为什么'(3,7)'与'(0,2)'重叠? – jacobm