重複するセッションの数を計算する次のコードブロックがあります。異なる間隔が与えられた場合、タスクは、これらの間隔間のオーバーラップの最大数をいつでも出力し、オーバーラップした間隔を見つけることです。
def overlap(v):
# variable to store the maximum
# count
ans = 0
count = 0
data = []
# storing the x and y
# coordinates in data vector
for i in range(len(v)):
# pushing the x coordinate
data.append([v[i][0], 'x'])
# pushing the y coordinate
data.append([v[i][1], 'y'])
# sorting of ranges
data = sorted(data)
# Traverse the data vector to
# count number of overlaps
for i in range(len(data)):
# if x occur it means a new range
# is added so we increase count
if (data[i][1] == 'x'):
count += 1
# if y occur it means a range
# is ended so we decrease count
if (data[i][1] == 'y'):
count -= 1
# updating the value of ans
# after every traversal
ans = max(ans, count)
# printing the maximum value
print(ans)
# Driver code
v = [[ 1, 2 ], [ 2, 4 ], [ 3, 6 ],[3,8]]
overlap(v)
これはを返します3
。しかし、既存のアプローチを変更して最大重複間隔を返すための最良の方法は何でしょうか?この場合、どちらである必要があります[3,4]
。
(コレクションからの)counterオブジェクトを使用して、交差するサブ間隔のリストを作成し、それらと交差する元の間隔の数を数えることができます。リスト内の各間隔は、カウントを累積するために、これまでに見つかったすべてのサブ間隔と交差します。
v = [[ 1, 2 ], [ 2, 4 ], [ 3, 6 ],[3,8]]
from collections import Counter
overCounts = Counter()
for vStart,vEnd in v:
overlaps = [(max(s,vStart),min(e,vEnd)) for s,e in overCounts
if s<=vEnd and e>=vStart]
overCounts += Counter(overlaps + [(vStart,vEnd)])
interval,count = overCounts.most_common(1)[0]
print(interval,count) # (3,4) 3
オーバーラップリストは、これまでに見つかったサブインターバルとの交差を検出します。s<=vEnd and e>=vStart
間隔(s、e)が間隔(vStart、vEnd)と交差すると、Trueを返します。交差する間隔については、交差の開始と終了(サブ間隔)が必要です。交差点は最大の始点で始まり、最小の終点で終わります。したがって、開始位置のmax()と終了位置のmin()を使用して、サブインターバルを形成します。(max(s,vStart),min(e,vEnd))
vStart vEnd
[--------------------]
[--------------------------]
s e
[-------------]
--max-> <----min-----
[編集]正直なところ、私はあなたのオリジナルのアプローチが私のものよりも好きです。O(NLogN)時間で応答しますが、データによってはO(N ^ 2)まで上がる可能性があります。
元のアプローチの結果に対応するサブインターバルをキャプチャするには、最後に検出された開始位置を追跡する変数を追加し、「y」条件内でより高いカウントの検出を移動する必要があります。
例えば:
lastStart = maxStart = maxEnd = None
# ...
if (data[i][1] == 'x'):
lastStart = data[i][0] # last start of sub-interval
count += 1
if (data[i][1] == 'y'):
if count > ans: # detect a greater overlap
maxStart = lastStart # start of corresponding sub-interval
maxEnd = data[i][0]
ans = count
count -= 1
# ans = max(ans, count) <-- removed
# ...
また、accumulateを使用して実装することもできます。
v = [[ 1, 2 ], [ 2, 4 ], [ 3, 6 ],[3,8]]
from itertools import accumulate
edges = sorted((p,e) for i in v for p,e in zip(i,(-1,1)))
counts = accumulate(-e for _,e in edges)
starts = accumulate((p*(e<0) for p,e in edges),max)
count,start,end = max((c+1,s,p) for c,s,(p,e) in zip(counts,starts,edges) if e>0)
print(count,[start,end]) # 3 [3, 4]
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加