ERPシステムはバックグラウンドジョブを実行するためのサブシステムです。送信、開始、終了時間のタイムスタンプを含む、テーブル内のジョブに関するさまざまなメタデータを追跡します。
日ごとに詳細なジョブシステムのパフォーマンスを示すレポートを作成しています。 1つのKPIは、同時に実行されるジョブの最大数です。私が現在使用しているアルゴリズムは次のとおりです。
dim cnt as integer 'number of overlapping jobs
dim max as integer 'maximum number of jobs running at one time
for each Job where
Job.SubmitTs = today
'bJob is a 2nd instance of Job
for each bJob where
bJob.SubmitTs = today and
bJob.StartTs <= Job.EndTs and
bJob.EndTs >= Job.EndTs
cnt = cCnt + 1
next
if cnt > max then max = cnt
next
このアルゴリズムの問題は、すべてのループのために非常に遅いということです。これを実装するより速い方法があるかどうか疑問に思っていましたか?
編集 SQLクエリを使用してデータにアクセスできません。
次に、次のように(2 * N)要素を反復します。
for each element X
do
if(X.type == start)
counter++
else
counter--
ans=max(ans, counter);
end
複雑さ:O(n.log(n))ソート済み構造の初期ビルド用+ O(n) forその要素の反復。
編集:配列が使用されることがGiorgioによって提案されていますが、これはより良いオプションです。 (元々は赤/黒のツリーを使用するという提案でしたが、タスクを削除する機能は必要ないようなので、順序を維持するのは簡単です)。
SQLはデータの並べ替え方法を認識しており、エンジンが可能な限り最も効率的なアルゴリズム(O(n log(n))
)を使用している一方で、結果セットがRAM(配列がRAMに収まらない場合に失敗するK.Steffの回答とは異なります)Pythonでは:
_import sqlite3
connection = sqlite3.connect("database.db")
cursor = connection.cursor()
cursor.execute("SELECT isStart from (" +
" SELECT startTime AS time, 1 AS isStart FROM myTable " +
" UNION ALL " +
" SELECT endTime as time, -1 AS isStart FROM myTable " +
" ORDER BY time ASC, isStart ASC" +
")")
maxOverlap = 0
currentOverlap = 0
for (isStart,) in cursor:
currentOverlap += isStart
maxOverlap = max(maxOverlap, currentOverlap)
print maxOverlap
_
_isStart ASC
_の順序が必要であるため、間隔_[10,15]
_と_[15,23]
_が重複しているとは見なされないことに注意してください。
さらなる改善のために、おそらく列startTimeおよびendTimeにインデックスがあるため、SQLエンジンはすでにソートされた2つのテーブルを効率的にマージし、O(n)
操作(O(log(n))
次に、各行の挿入時に要素がインデックスに追加されたときに発生しますが、とにかくすでに持っています)。 SQLエンジンが効率的なマージを行うのに十分スマートでない場合は、オンザフライで実行します(まだpythonで):
_import sqlite3
connection = sqlite3.connect("database.db")
cursorStart = connection.cursor()
cursorStart.execute("SELECT startTime FROM myTable ORDER BY startTime ASC")
cursorEnd = connection.cursor()
cursorEnd.execute("SELECT endTime FROM myTable ORDER BY endTime ASC")
maxOverlap = 0
currentOverlap = 0
currentStart = cursorStart.fetchone()
currentEnd = cursorEnd.fetchone()
while currentStart is not None and currentEnd is not None:
if currentStart < currentEnd:
currentOverlap += 1
currentStart = cursorStart.fetchone()
else:
currentOverlap -= 1
currentEnd = cursorEnd.fetchone()
maxOverlap = max(maxOverlap, currentOverlap)
print maxOverlap
_