一定時間と償却一定時間は実質的に同等と見なされますか?


16

一定時間(O(1))で追加とランダム削除を可能にするRandomQueueを書く必要があります。

私の最初の考えは、ある種の配列(ArrayListを選択しました)でそれをバックアップすることでした。配列はインデックスを介して常にアクセスできるためです。

しかし、ドキュメントを見ると、ArrayListsの追加はAmortized Constant Timeと見なされていることに気付きました。これは、追加には基になる配列(O(n))の再割り当てが必要になる可能性があるためです。

Amortized Constant TimeとConstant Timeは事実上同じですか、または追加ごとに完全な再割り当てを必要としない構造を調べる必要がありますか?

配列ベースの構造は別として(私が知っている限り、常に一定の時間での償却が追加されます)、要件を満たすものは考えられないため、これを求めています:

  • ツリーベースのものはすべて、せいぜいO(log n)アクセスを持ちます。
  • リンクされたリストには、潜在的にO(1)が追加される可能性があります(テールへの参照が保持される場合)が、ランダムな削除はせいぜいO(n)でなければなりません。

完全な質問は次のとおりです。私がいくつかの重要な詳細にlazした場合に備えて:

RandomQueueを設計および実装します。これはQueueインターフェースの実装であり、remove()操作は、現在キューにあるすべての要素の中からランダムに均一に選択された要素を削除します。(RandomQueueは、要素を追加したり、ランダムな要素に到達してやみくもに削除できるバッグと考えてください。)RandomQueueのadd(x)およびremove()操作は、操作ごとに一定の時間で実行する必要があります。


割り当ては、ランダムな削除の実行方法を指定していますか?削除するインデックスまたはキュー要素への参照が与えられていますか?

それは詳細を与えません。要件は、Queueインターフェイスを実装する構造であり、O(1)の追加と削除があります。
発癌性

余談ですが、O(n)が増加するサイズ変更可能な配列には、必ずしもO(1)が追加されるわけではありません。これは、配列の成長方法に依存します。一定量aでの成長は、まだ追加のO(n)です(1/aO(n)操作の可能性があります)が、一定の要因での成長は、a > 1追加で償却されたO(1)です:(1/a)^nOの可能性があります(n)操作。ただし、その確率は大の場合ゼロに近づくn
アモン

ArrayListsは後者を正しく使用していますか?
発がん性物質

1
質問の著者(私)は、償却された一定時間のソリューションを考えていました。次のエディションでそれを明確にします。(一定時間の技術使用してここに達成することができる最悪の場合が、デ償却
特許モリン

回答:


10

Amortized Constant Timeは、ほとんどの場合、Constant Timeと同等と見なすことができます。アプリケーションの詳細と、このキューに対して行う予定の使用タイプを知らなくても、ほとんどの場合、カバーされます。

配列リストには容量の概念があり、これは基本的に、これまでに要求されたアイテムの最大サイズ/長さ/数に等しいです。したがって、最初に配列リストはアイテムを追加し続けると容量を増やすために再割り当てを続けますが、ある時点で単位時間あたりに追加されるアイテムの平均数は必然的に平均アイテム数と一致します単位時間ごとに削除されます(そうしないと最終的にはメモリが不足します)。この時点で、配列はそれ自体の再割り当てを停止し、すべての追加はO(1)の一定時間で満たされます。

ただし、デフォルトでは、配列リストからのランダムな削除はO(1)ではなく、O(N)であることに注意してください。これは、配列リストが、削除されたアイテムの後のすべてのアイテムを1つ下の位置に移動して削除される項目。O(1)を実現するには、デフォルトの動作をオーバーライドして、削除されたアイテムを配列リストの最後のアイテムのコピーに置き換え、最後のアイテムを削除して、アイテムが移動されないようにする必要があります。しかし、それを行うと、キューはもう完全になくなります。


1
くそー、削除の良い点; 私はそれを考慮しませんでした。そして、要素をランダムに削除しているので、技術的にはそれがもはやその意味でのキューではないということではないのでしょうか?
発癌性

はい、それはあなたが本当にそれをキューとして扱っていないことを意味します。しかし、削除するアイテムをどのように見つけるつもりなのかわかりません。それらを見つけるメカニズムが、それらが追加された順序でキューに存在することを期待している場合、あなたは運が悪いです。アイテムの順序が文字化けしてもかまわない場合は、大丈夫です。
マイクナキス

2
期待はRandomQueueQueueインターフェイスを実装し、提供されたremoveメソッドが頭をポップする代わりにランダムに削除することです。したがって、特定の順序に依存する方法はないはずです。そのランダムな性質を考えると、ユーザーは特定の順序を維持することを期待すべきではないと思います。明確にするために、質問で課題を引用しました。ありがとうございました。
発癌性

2
はい、そうです、アイテムの削除が私が提案した方法で行われたことを確認するだけで大​​丈夫だと思われます。
マイクナキス

気にしない場合、最後にもう1つ。私はさらに考えましたが、「真の」O(1)の追加と「真の」O(1)のランダムな削除の両方を行うことはできないようです。2の間のトレードオフになります。削除を行うが追加はしない単一割り当て構造(配列など)、または追加を行うが削除はしないリンクリストのようなチャンク割り当て構造のいずれかがあります。これは本当ですか?再びありがとう。
発癌性

14

質問は具体的には一定の時間を求めているようで、償却された一定の時間ではありません。したがって、引用された質問に関しては、いいえ、それらは事実上同じではありません*。しかし、それらは実際のアプリケーションにありますか?

償却定数の典型的な問題は、累積した負債を時々支払わなければならないことです。そのため、挿入は一般的に一定ですが、新しいブロックが割り当てられたときにすべてを再挿入するオーバーヘッドが発生する場合があります。

一定の時間と償却された一定の時間との差がアプリケーションに関連する場合、この非常に遅い速度が許容されるかどうかによって異なります。非常に多数のドメインの場合、これは一般に問題ありません。特に、コンテナの有効な最大サイズ(キャッシュ、一時バッファ、作業コンテナなど)がある場合、実行時に1回だけ効果的に支払うことができます。

応答の重要なアプリケーションでは、これらの時間は許容できない場合があります。短時間のターンアラウンド保証を満たす必要がある場合、それを時々超えるアルゴリズムに頼ることはできません。私は以前にそのようなプロジェクトに取り組んだことがありますが、非常にまれです。

また、このコストが実際にどれだけ高いかにも依存します。ベクターは、再割り当てコストが比較的低いため、パフォーマンスが高い傾向があります。ただし、ハッシュマップに移動すると、再割り当てがずっと高くなる可能性があります。繰り返しますが、ほとんどのアプリケーション、特にコンテナ内のアイテムに上限がある特に長寿命のサーバーでは、おそらく問題ありません。

*ただし、ここには少し問題があります。汎用コンテナを挿入のために一定の時間にするために、次の2つのいずれかを保持する必要があります。

  • コンテナの最大サイズは固定されている必要があります。または
  • 個々の要素のメモリ割り当ては一定時間であると想定できます。

ここで使用する「肝臓サーバー」は奇妙な言い回しのようです。「ライブサーバー」を意味するのでしょうか?
ピーターギアケンズ

6

スループットとレイテンシのどちらを最適化するかによります:

  • 遅延に敏感なシステムには、一貫したパフォーマンスが必要です。このようなシナリオでは、システムの最悪の場合の動作を強調する必要があります。例としては、一貫したフレームレートを達成したいゲームなどのソフトリアルタイムシステムや、特定の厳しい時間枠内で応答を送信する必要があるWebサーバーがあります。CPUサイクルの浪費は遅れるよりも優れています。
  • スループットを最適化したシステムは、最大量のデータを長期的に処理できる限り、時折のストールを気にしません。ここでは、主に償却後のパフォーマンスに関心があります。これは一般に、数値計算やその他のバッチ処理ジョブの場合です。

1つのシステムには、異なるカテゴリに分類する必要のある異なるコンポーネントを含めることができます。たとえば、最新のテキストプロセッサには、遅延に敏感なUIスレッドがありますが、スペルチェックやPDFエクスポートなどの他のタスク用にスループットが最適化されたスレッドがあります。

また、アルゴリズムの複雑さは、多くの場合、私たちが考えるほど重要ではありません。問題が特定の数に制限されている場合、実際の測定されたパフォーマンス特性は「非常に大きいnの」動作よりも重要です。


残念ながら、私はほとんど背景がありません。問題は「RandomQueueのadd(x)およびremove()操作は、操作ごとに一定の時間で実行する必要があります」で終わります。
発癌性

2
@Carcigenicateは、システムが遅延に敏感であるという事実を知っている場合を除き、償却された複雑さを使用してデータ構造を選択するだけで十分です。
アモン

これはプログラミングの練習かテストかもしれないという印象があります。そして確かに簡単なものではありません。それが非常にまれなことであることは絶対に真実です。
gnasher729

1

「償却された一定時間」アルゴリズムを求められた場合、アルゴリズムに時間がかかることがあります。たとえば、C ++でstd :: vectorを使用する場合、そのようなベクターには10個のオブジェクトにスペースが割り当てられている可能性があり、11番目のオブジェクトを割り当てると、20個のオブジェクトにスペースが割り当てられ、10個のオブジェクトがコピーされ、11番目が追加されますかなりの時間がかかります。しかし、100万個のオブジェクトを追加すると、999,980の高速操作と20の低速操作があり、平均時間が高速になります。

「一定時間」アルゴリズムを要求された場合、すべての単一操作に対して、アルゴリズムは常に高速でなければなりません。これは、各単一操作が常に高速であるという保証が必要なリアルタイムシステムにとって重要です。「一定の時間」はほとんどの場合必要ありませんが、「償却された一定の時間」と同じではありませ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.