找到最大间隔数与 python 重叠的点的最有效方法

The most efficient way to find the point where maximum number of intervals overlap with python

假设我有一个记录用户从某个服务器进入和退出时间的日志记录。我需要找到最大会话的时间。如果有多个可能的答案,应选择最小的答案。输入包含第一行的会话数。

例子 输入:

5
4 5
0 3
1 9
7 8
2 6

输出:

2

我试过这个脚本:

from collections import Counter, OrderedDict

load = Counter()
with open("input.txt", "r") as f:
    n = int(f.readline())
    for i in range(n):
        session = f.readline()
        session = session.split()
        load.update(range(int(session[0]), int(session[1])+1))

load = load.most_common()
i = 0
max = load[0][1]
candidates = []
while load[i][1] == max:
    candidates.append(load[i][0])
    i += 1
print(min(candidates))

首先,我使用Counter()来计算所有点的出现次数。其次,我使用 load = load.most_common() 按出现次数对生成的字典进行排序。最后我找到所有键的最小值和相应的最大值(=出现次数)。

其实如果Counter()返回一个key排序的dict,就简单多了。

无论如何,这是我的家庭任务,它在其中一个测试输入上运行超过 1 秒(给定时间限制)。可以做些什么来加快速度?我读过有关间隔树的信息,但不确定它是否相关。

这个问题的快速解决方案是将 +1、-1 存储在 enter/exit 次 - 然后对 dict-keys 进行排序并递增求和,然后获得最大值:

data = """5
4 5
0 3
1 9
7 8
2 6"""
with open("input.txt", "w") as f:
    f.write(data) 

d = {}
with open("input.txt", "r") as f:
    next(f)
    for line in f:  
        if line.strip():
            start, stop = map(int,line.strip().split())
            d.setdefault(start,0)
            d[start] += 1
            d.setdefault(stop,0)
            d[stop] -= 1

maxx = 0
s = 0
max_idx = 0

# iteratively summ over sorted times from dict
for idx,key in enumerate(sorted(d)):
    s += d[key]
    if maxx < s:  # remembert new max_idx and max
        maxx = s
        max_idx = idx
print(max_idx)

如果 defaultdict(int) 仍然太慢而无法解决您的挑战,您可以使用 defaultdict(int)。

假设 insouts 是登录和注销时间:

ins = [4,0,1,7,2]
outs = [5,3,9,8,6]

将它们组合在一个排序列表中,并用数字符号表示它是 "arrival"(正数)还是 "departure"(负数):

times = sorted(ins + [-x for x in outs], key=abs)

现在,遍历列表并计算 "arrivals" 和 "departures" 的发生次数:

lmax = -1
logged = 0
for t in times:
    if t >= 0:
        logged += 1
        if logged > lmax:
            tmax = t
            lmax = logged
    else:
        logged -= 1

print(tmax, lmax)
#2 3