web-dev-qa-db-ja.com

一定の償却時間

アルゴリズムの時間の複雑さについて話すとき、「一定の償却時間」とはどういう意味ですか?

385
VarunGupta

単純な用語で説明された償却時間:

100万回と言う操作を行う場合、その操作の最悪のケースやベストケースはあまり気にしません。何百万回操作を繰り返すと、合計でどれだけの時間がかかるかが気になります。

そのため、動作が時々非常に遅くなるかどうかは問題ではありません。ただし、「しばらく」が遅くなるのを遅らせるのに十分な場合です。基本的に償却時間とは、「多くの操作を行う場合、操作ごとにかかる平均時間」を意味します。償却時間は一定である必要はありません。線形および対数の償却時間またはその他のものを使用できます。

新しいアイテムを繰り返し追加する動的配列のマットの例を見てみましょう。通常、アイテムの追加には一定の時間がかかります(つまり、O(1))。ただし、アレイがいっぱいになるたびに、2倍のスペースを割り当て、データを新しい領域にコピーして、古いスペースを解放します。割り当てと解放が一定の時間で実行されると仮定すると、この拡大プロセスにはO(n)時間かかります。ここで、nは配列の現在のサイズです。

そのため、拡大するたびに、最後の拡大の約2倍の時間がかかります。しかし、あなたはそれをする前に2倍も待っていました!したがって、各拡大のコストは、挿入の間で「分散」することができます。これは、長期的には、配列にmアイテムを追加するのにかかる合計時間がO(m)であるため、償却時間(挿入ごとの時間)はO(1)になることを意味します。 。

734
Artelius

つまり、時間の経過とともに、最悪のシナリオはデフォルトでO(1)、つまり一定時間になります。一般的な例は、動的配列です。新しいエントリに既にメモリを割り当てている場合、追加するのはO(1)になります。割り当てていない場合は、たとえば現在の2倍の量を割り当てます。この特定の挿入は、notO(1)ではなく、何か他のものになります。

重要なことは、アルゴリズムが一連の操作の後、高価な操作が償却され、それによって操作全体O(1)がレンダリングされることを保証することです。

または、より厳密には、

定数cがあり、長さLのevery一連の操作(また、コストのかかる操作で終わるもの)の場合、時間はc * L(ありがとう RafałDowgird

55

それについての直感的な考え方を開発するには、 動的配列 (たとえば、C++のstd::vector)に要素を挿入することを検討してください。配列にN個の要素を挿入するために必要な操作数(Y)の依存関係を示すグラフをプロットしてみましょう。

plot

黒いグラフの垂直部分は、配列を拡張するためのメモリの再割り当てに対応しています。ここでは、この依存関係を大まかに線として表すことができます。そして、この直線の方程式はY=C*N + bCは定数、b = 0の場合)です。したがって、N個の要素を配列に追加するにはC*N操作を、1つの要素を追加するにはC*1操作を費やす必要があります(償却された一定時間)。

18
Megamozg

3回繰り返し読んだ後、Wikipediaの説明が役に立つことがわかりました。

ソース: https://en.wikipedia.org/wiki/Amortized_analysis#Dynamic_Array

「ダイナミックアレイ

動的配列のプッシュ操作の償却分析

JavaのArrayListなど、要素が追加されるにつれてサイズが大きくなる動的配列を検討してください。サイズ4の動的配列から始めた場合、4つの要素をプッシュするのに一定の時間がかかります。ただし、5番目の要素をその配列にプッシュすると、現在のサイズの2倍の新しい配列(8)を作成し、古い配列を新しい配列にコピーしてから新しい要素を追加する必要があるため、時間がかかります。次の3つのプッシュ操作も同様に一定の時間を要し、その後の追加では、配列サイズをさらに2倍に遅くする必要があります。

一般に、サイズnの配列へのプッシュnの任意の数を考慮する場合、プッシュ操作は、サイズ倍増操作を実行するのにO(n)時間を要する最後の操作を除いて一定の時間がかかることに気づきます。合計n個の操作があったため、これの平均を取ることができ、動的配列に要素をプッシュするには、O(n/n)= O(1)、一定時間がかかることがわかります。

簡単な話としての私の理解:

たくさんのお金があると仮定します。そして、あなたは部屋にそれらを積み重ねたいです。また、現在または将来必要な限り、長い手足があります。また、すべてを1つの部屋に入れる必要があるため、簡単にロックできます。

だから、あなたは部屋の端/隅に右に行き、それらを積み重ね始めます。それらを積み重ねると、ゆっくりと部屋のスペースがなくなります。ただし、記入すると簡単にスタックできました。お金を得た、お金を入れて。簡単です。 O(1)です。以前のお金を移動する必要はありません。

部屋に空きがなくなったら。もっと広い部屋が必要です。ここに問題があります。1つの部屋しか持てず、1つのロックしか持てないため、その部屋にある既存のお金をすべて新しい大きな部屋に移動する必要があります。したがって、すべてのお金を小さな部屋から大きな部屋に移動します。つまり、それらすべてを再度スタックします。ですから、以前のお金をすべて移動する必要があります。したがって、O(N)です。 (Nは前のお金の合計数と仮定)

つまり、N回、1回の操作まで簡単でしたが、より大きな部屋に移動する必要がある場合は、N回の操作を行いました。つまり、平均すると、最初の1回の挿入であり、別の部屋への移動中にさらに1回移動します。合計2つの操作、1つの挿入、1つの移動。

Nが小さな部屋でも100万のように大きいと仮定すると、Nと比較した2つの操作(100万)は実際には同等の数ではないため、一定またはO(1)と見なされます。

上記のすべてを別の大きな部屋で行い、再び移動する必要があると仮定します。まだ同じです。たとえば、N2(たとえば、10億)は、大きな部屋の新しい金額です

したがって、N2があります(すべての部屋が小さい部屋から大きい部屋に移動するため、これには以前のN

まだ2つの操作だけが必要です。1つは大きな部屋に挿入し、もう1つの移動操作はさらに大きな部屋に移動します。

したがって、N2(10億)の場合でも、それぞれ2回の操作になります。再び何もありません。したがって、定数、またはO(1)

そのため、NがNからN2、またはその他に増加しても、それほど重要ではありません。まだ一定であるか、NのそれぞれにO(1)操作が必要です。


ここで、Nが1で非常に小さく、お金の数が少なく、部屋が非常に小さく、お金の数が1つだけであると仮定します。

部屋にお金を入れるとすぐに部屋がいっぱいになります。

大きな部屋に行くときは、そこにもう1枚のお金、合計2カウントしか入らないと仮定します。つまり、前のお金が移動し、さらに1つ移動しました。そして再び満たされます。

このように、Nはゆっくりと成長し、前の部屋からすべてのお金を移動しているため、一定のO(1)ではありませんが、収まるのは1つだけです。

100回後、新しい部屋は、以前の100カウントのお金に対応し、もう1お金を収容できます。 O(N + 1)はO(N)であるため、これはO(N)です。つまり、100または101の次数は同じで、どちらも数百です。 。

したがって、これはお金(変数)に部屋(またはメモリ/ RAM)を割り当てる非効率的な方法です。


したがって、2の累乗でより多くのスペースを割り当てるのが良い方法です。

最初の部屋のサイズ= 1カウントのお金に適合
2番目の部屋のサイズ=お金の4カウントに適合
3番目の部屋のサイズ=お金の8カウントに適合
4番目の部屋のサイズ= 16カウントのお金に適合
5番目の部屋のサイズ= 32枚のお金に適合
6番目の部屋のサイズ= 64カウントのお金に適合
7番目の部屋のサイズ= 128カウントのお金に適合
8番目の部屋のサイズ= 256カウントのお金に適合
9番目の部屋のサイズ= 512カウントのお金に適合
10番目の部屋のサイズ= 1024枚のお金に適合
11番目の部屋のサイズ= 2,048カウントのお金に適合
...
16番目の部屋のサイズ= 65,536カウントのお金に適合
...
32番目の部屋のサイズ= 4,294,967,296枚のお金に適合
...
64番目の部屋のサイズ= 18,446,744,073,709,551,616の金額に適合

なぜこれが良いのですか?それは、RAMのメモリ量と比較して、最初はゆっくりと成長し、後で速く成長するように見えるためです。

これは、最初のケースでは良いのですが、お金あたりの総作業量が固定(2)であり、部屋のサイズ(N)と比較できないため、初期段階で取った部屋も多すぎる可能性があるため便利です大きい場合(100万)は、最初のケースで節約するためにそれほど多くのお金を得ることができるかどうかによっては完全に使用できない場合があります。

ただし、最後のケースである2の累乗では、RAMの制限内で増加します。そのため、2のべき乗を増やしても、Armotized分析は一定のままであり、現在の限られたRAMに適しています。

12

上記の説明は、複数の操作で「平均」を取るという考え方である集計分析に適用されます。 Bankers-methodまたはPhysicists Methods of Amortized分析にそれらがどのように適用されるかわかりません。

今。私は正しい答えを正確に確信していません。しかし、それは物理学者とバンカーの両方の方法の基本的な条件と関係があるでしょう:

(償却原価の合計)> =(実際原価の合計)。

私が直面する主な困難は、運用の償却漸近コストが通常の漸近コストと異なることを考えると、償却コストの重要性をどのように評価するかわからないということです。

それは誰かが私に償却費を与えたとき、私はそれが通常の漸近的な費用と同じではないことを知っています。私はその償却費からどのような結論を導き出しますか?

一部の操作が過負荷になっている一方で、他の操作が過少になっている場合があるため、1つの仮説として、個々の操作の償却コストを引用しても意味がないと考えられます。

たとえば、フィボナッチヒープの場合、「減少キーの償却コストをO(1)」と見積もることは意味がありません。

OR

償却原価に関する理由は次のような別の仮説を立てることができます。

  1. 費用のかかる操作の前に、複数の低コスト操作が行われることを知っています。

  2. 分析のために、いくつかの低コストの操作を過充電します。これは、それらの漸近コストが変わらないということです。

  3. これらの低コストでの運用が増えることで、高価な運用にはより小さな漸近コストがあることを証明できます。

  4. したがって、n個の操作のコストのASYMPTOTIC-BOUNDを改善/減少させました。

したがって、償却原価分析+償却原価限界は現在、高価な操作にのみ適用できます。安価な操作には、通常の漸近コストと同じ漸近償却コストがあります。

1
Misraji