首先,我从您的示例中假设(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)
1中做到这一点,因此步骤 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
将 print4
来自这些重叠:
(0,2) - (1,4)
(1,4) - (3,7)
(3,7) - (5,8)
(11,14) - (14,17)
请注意,我们无法获得重叠间隔,因为在最坏的情况下会有O(n^2)
重叠,无法及时打印O(n log n)
。
1实际上,Fenwick 树在O(log M)
时间上进行计数,其中M
是区间中不同值的最大可能数量。请注意,M <= 2n
因为只能有那么多不同的值。所以说 Fenwick TreeO(log n)
及时计算也是正确的。