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

时间:2018-12-22 20:05:28

标签: python algorithm intervals

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

示例 输入:

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()返回了按键排序的字典,则它将简单得多。

无论如何,这是我的主任务,并且在其中一个测试输入上运行超过1秒(给定时间限制)。可以采取什么措施来加快速度?我已经阅读了有关间隔树的信息,但不确定是否相关。

2 个答案:

答案 0 :(得分:1)

为此的快速解决方案是在进入/退出时间存储+ 1,-1-然后对字典键进行排序并对其求和,然后求和,然后得到最大值:

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)仍然太慢而无法解决挑战,则可以使用。

答案 1 :(得分:1)

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

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

在一个排序的列表中用数字的符号将其组合起来,以表明它是“到达”(正)还是“出发”(负):

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

现在,遍历列表并计算发生的“到达”和“离开”:

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
相关问题