web-dev-qa-db-ja.com

O(nlog(n))で「最大」の重複する区間ペアを見つける

問題の説明

入力 n間隔のセット; {[s_1、t_1]、[s_2、t_2]、...、[s_n、t_n]}。

出力間隔のペア; {[s_i、t_i]、[s_j、t_j]}、maximumがすべての区間ペア間で重複しています。

入力間隔:{[1、10]、[2、6]、[3,15]、[5、9]}

->可能な6つの間隔ペアがあります。これらのペアの中で、[1,10]と[3,15]の重なりが最大になるのは7です。

出力:{[1,10]、[3,15]}

ナイーブアルゴリズムは、現在の最大オーバーラップ値を追跡しながら、n個の間隔すべてを相互に比較するブルートフォース方式になります。この場合、時間計算量はO(n ^ 2)になります。

区間木重複区間の最大数に関する多くの手順を見つけることができました-)および重複しない間隔の最大セットですが、この問題については何もありません。上記のアルゴリズムで与えられたアイデアを使用できるかもしれませんが、私はそれを思い付くことができませんでした。

私は何時間もかけて素晴らしい解決策を見つけようとしましたが、この時点で助けが必要だと思います。

どんな提案も役に立ちます!

12
user1751434

まず、間隔を並べ替えます。最初に左のエンドポイントで昇順で並べ替え、次に— 2番目の基準として—右のエンドポイントで降順で並べ替えます。この回答の残りの部分では、間隔はすでにソートされた順序になっていると想定します。

ここで、可能な最大の重なりがどのようになるかについて、2つの可能性があります。

  • それが完全にカバーするのは、ある間隔とそれ以降の間隔の間である可能性があります。
  • それが完全にカバーするのは、ある間隔とその次の間隔の間にある可能性がありますしません

以下を追跡しながら、間隔を反復することにより、O(n)時間で両方のケースをカバーできます。

  • これまでに見た中で最大のオーバーラップ、および関連する間隔のペア。
  • 私たちが見た最新の間隔は、それを[〜#〜] l [〜#〜]と呼びます。これは、前任者のいずれによっても完全にはカバーされていませんでした。 (このための重要な洞察は、間隔の順序付けのおかげで、間隔がその前任者のいずれかによって完全にカバーされているかどうか、したがって更新する必要があるかどうかを簡単に判断できることです[〜#〜] l [〜#〜] —現在の[〜#〜] l [〜#〜]で完全にカバーされているかどうかを確認するだけで、[〜#〜 ] l [〜#〜]最新O(1)時間。)

そして、各区間のオーバーラップを[〜#〜] l [〜#〜]で計算します。

そう:

result := []
max_overlap := 0
L := sorted_intervals[1]
for interval I in sorted_intervals[2..n]:
    overlap := MIN(L.right, I.right) - I.left
    if overlap >= max_overlap:
        result := [L, I]
        max_overlap := overlap
    if I.right > L.right:
        L := I

したがって、総コストは間隔を並べ替えるコストであり、O(n log n)時間である可能性が高いですが、O(n =)バケットソートや基数ソートなどを使用できる場合。

13
ruakh