首先,我从您的示例中假设 (0,1) 和 (1,2) 重叠。
顺便说一句,您的示例不正确,(3,7) 与 (0,2) 不重叠
解决这个问题的一种方法是:
- 根据起点对区间进行排序
- 从最低点到最高点迭代
2a。计算大于或等于当前起点的先前终点的数量。
2b。当前终点的计数加一。
第一步可以在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
将打印来自这些重叠的4:
(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 Tree 在O(log n) 时间进行计数也是正确的。