時間帯重複チェックの計算量と前提条件
お題:時間帯重複チェック(応用編) - No Programming, No Life に関して、解法は2種類に大別できるようです。
解法の分類
離散時刻方式
「時間帯(何時何分から何時何分まで)に含まれる時刻(何時何分)の最小単位が1分」であることに注目した方式です。とりあえず、このように名づけてみました。
典型的な実装は下記のようになります。
- 与えられた時間帯のひとつひとつを1分ごとの時刻に分解する → O(N)
- 重複する時刻を抽出する → O(N)
- 連続する抽出時刻をまとめて時間帯に再構成する → O(N)
この方式のメリットは、計算量のオーダをO(N)に抑えられる点です。
[代表例]
時刻全順序方式
一方、純粋に時刻の大小関係(前後関係)のみに基づいてアルゴリズムを構築することもできます。
典型的な実装では下記のようになります。
- 与えられた時間帯を開始時刻で整列する → O(NlogN)
- 整列済の時間帯が重なる部分をシーケンシャルに抜き出す → O(N)
この方式のメリットは、時刻指定を細かくしても問題をきたさない点が挙げられます。例えば、時刻の最小単位を「何分」ではなく「何秒」まで指定することになった状況を考えてみましょう。前述の離散時刻方式では、60倍の離散時刻が生じますが、この方式ではなんら不都合は生じません。
その一方で、デメリットもあります。どんなに最良の実装を頑張っても、計算量はO(NlogN)になってしまう点です。
[代表例]
- dev68さん:時間帯重複チェック(応用編)その2 - コードの恵み
- matarilloさん:C#で時間帯重複チェック(応用編) - 平々毎々(アーカイブ)
キーポイント
分類のキーポイントが、2011-03-31 - コードの恵みにて簡潔明快に述べられています。
フラグ方式は bucket sort のように限定条件に気づいている
この「限定条件」をもう少しまわりくどく説明したのが、上記の分類に相当すると思います。
私のつたない日本語では、これ以上、明快な説明をできませんので、答案:時間帯重複チェック(応用編) - 一番良いアルゴリズムを頼む · GitHubにコードで示します。
ポイントは、
- 通常のソートを用いれば計算量がO(NlogN)になる;bucket ソートを用いればO(N)になる
- 通常のソートを用いる場合は、時刻の離散性を用いていない(例えば、時刻がInt でなく Double でも動く)