O(log n)
時間の複雑さよりも時間の複雑さを好むケースはありますO(1)
か?それともO(n)
へO(log n)
?
例はありますか?
O(log n)
時間の複雑さよりも時間の複雑さを好むケースはありますO(1)
か?それともO(n)
へO(log n)
?
例はありますか?
回答:
大きなO時間の複雑性が低いアルゴリズムよりも高いアルゴリズムを好む理由は数多くあります。
10^5
は1/10^5 * log(n)
(O(1)
vs O(log(n)
)よりもbig-Oの観点からは優れていますが、最も妥当な場合n
は、最初のアルゴリズムの方が優れています。たとえば、行列の乗算は最も複雑ですO(n^2.373)
が、定数が非常に高いため、(私の知る限り)計算ライブラリでは使用されません。O(n*log(n))
かO(n^2)
アルゴリズムを使用するかはほとんど問題になりません。O(log log N)
、アイテムを見つけるのに時間の複雑さをが、同じものを見つけるバイナリツリーもありますO(log n)
。非常に多くのn = 10^20
違いがあったとしてもごくわずかです。O(n^2)
、O(n^2)
メモリを必要とするアルゴリズムを想像してみてください。それはより好ましいかもしれませんO(n^3)
O(1)
nが実際には大きくない場合は、時間と空間の場合があります。問題は、長い間待つことができるということですが、アルゴリズムで使用するのに十分な大きさのRAMを見つけることができることは間違いありませんO(n^2)
、クイックソートやマージソートよりも劣りますが、オンラインアルゴリズムとして、値のリストを(ユーザー入力として)受け取ったときに効率的にソートできます。値の完全なリスト。隠された定数は常に存在し、O(log n)アルゴリズムではより低くなる可能性があります。そのため、実際のデータの場合、実際にはより速く機能します。
スペースの問題もあります(トースターでの実行など)。
また、開発者の時間に関する懸念もあります。O(log n)は、実装と検証が1000倍も簡単です。
lg n
ので、非常に近いです。k
n
メモリにバインドされたアプリケーションについてまだ誰も言及していないことに驚いています。
アルゴリズムが複雑であるため(つまり、O(1)< O(log n))、または複雑さの前の定数が小さいため(つまり、2 n 2 <6 n 2)、浮動小数点演算が少ないアルゴリズムがある可能性があります。。いずれにせよ、低いFLOPアルゴリズムの方がメモリにバインドされている場合は、より多くのFLOPを使用するアルゴリズムを好むかもしれません。
「メモリバウンド」とは、常にキャッシュの外にあるデータにアクセスすることが多いということです。このデータをフェッチするには、実際にメモリ空間からキャッシュにメモリをプルしてから、データに対して操作を実行する必要があります。このフェッチ手順は、多くの場合非常に遅く、操作自体よりもはるかに遅くなります。
したがって、アルゴリズムがより多くの操作を必要とする場合(ただし、これらの操作はすでにキャッシュにある[したがってフェッチする必要はありません]のデータに対して実行されます)、アルゴリズムは実行する操作が少ないため、アルゴリズムのパフォーマンスは低下します(これは、 -実際のウォールタイムの観点からデータをキャッシュします(したがって、フェッチが必要です))。
O(logn)
オーバーO(1)
。実行可能なすべての状況で、n
メモリが少ないアプリケーションが、より高い複雑度でさえ、より速いウォールタイムで実行される状況を非常に簡単に想像できます。
データのセキュリティが懸念される状況では、より複雑なアルゴリズムの方がタイミング攻撃への耐性が優れている場合、より複雑なアルゴリズムの方が、それほど複雑ではないアルゴリズムよりも望ましい場合があります。
(n mod 5) + 1
、それはまだですがO(1)
、に関する情報を明らかにしますn
。したがって、漸近的に(そして場合によっては実際にさえ)遅くなる場合でも、よりスムーズなランタイムを備えたより複雑なアルゴリズムが望ましい場合があります。
Alistraはそれを釘付けにしたが、例を提供できなかったので、私はそうします。
あなたはあなたの店が売るもののために10,000のUPCコードのリストを持っています。10桁のUPC、価格の整数(ペニーでの価格)、およびレシートの説明の30文字。
O(log N)アプローチ:ソートされたリストがあります。ASCIIの場合は44バイト、Unicodeの場合は84バイト。または、UPCをint64として扱うと、42バイトと72バイトが得られます。10,000レコード-最高のケースでは、1メガバイト未満のストレージを見ています。
O(1)アプローチ:UPCを保存せず、代わりに配列へのエントリとして使用します。最も低いケースでは、テラバイトのストレージのほぼ3分の1を表示しています。
どちらの方法を使用するかは、ハードウェアによって異なります。ほとんどの合理的な最新の構成では、log Nアプローチを使用します。何らかの理由でRAMが非常に短いが大容量ストレージが十分にある環境で実行している場合、2番目のアプローチが正しい答えであると想像できます。ディスク上のテラバイトの3分の1は大したことではありません。ディスクの1つのプローブでデータを取得することは、何かの価値があります。単純なバイナリアプローチでは、平均で13になります。(ただし、キーをクラスタ化することで、これを保証された3回の読み取りに減らすことができ、実際には最初の読み取りをキャッシュすることに注意してください。)
malloc(search_space_size)
返されるものに添え字を付けるのは簡単です。
赤黒木を考えてみましょう。へのアクセス、検索、挿入、削除ができO(log n)
ます。にアクセスできる配列と比較してください。O(1)
残りの操作はO(n)
です。
そのため、アクセスするよりも頻繁に挿入、削除、または検索するアプリケーションと、これら2つの構造のみから選択する場合、赤黒ツリーを選択します。この場合、赤黒木のより面倒なO(log n)
アクセス時間を好むと言うかもしれません。
どうして?アクセスは私たちの最優先事項ではないためです。私たちはトレードオフを行っています。アプリケーションのパフォーマンスは、これ以外の要因により大きく影響されます。他のアルゴリズムを最適化することで大きな利益を得るので、この特定のアルゴリズムのパフォーマンスが低下することを許可します。
したがって、あなたの質問に対する答えは単にこれです:アルゴリズムの成長率が最適化したくないものである場合とき、最適化したいとき何か。他のすべての答えはこれの特別なケースです。ときどき、他の操作の実行時間を最適化します。時々、メモリを最適化します。時々、セキュリティを最適化します。メンテナンス性を最適化することもあります。開発時間を最適化することもあります。アルゴリズムの増加率が実行時間への最大の影響ではないことがわかっている場合、問題になるほど十分に低いオーバーライド定数でさえ、実行時間を最適化しています。(データセットがこの範囲外の場合、最終的に定数を支配するため、アルゴリズムの成長率を最適化します。)すべてにコストがあり、多くの場合、より高い成長率のコストを他のものを最適化するアルゴリズム。
O(log n)
が「赤黒木」であると宣言する「アクセス」と「検索」とは何ですか?挿入5
配列の位置2に[1, 2, 1, 4]
もたらすであろう[1, 2, 5, 1 4]
(要素4
インデックスが3から4に更新されます)。O(log n)
「ソートされたリスト」として参照する「赤黒木」でこの動作をどのように行うのですか?
はい。
実際のケースでは、短い文字列キーと長い文字列キーの両方を使用してテーブルルックアップを実行するテストをいくつか実行しました。
私たちは、使用std::map
、std::unordered_map
ハッシュとそのサンプルを最大で10文字列の長さが倍以上(これはまともですので、私達のキーは、GUID-ようになる傾向があり)、およびサンプルすべての文字(理論的には、衝突を軽減)というハッシュ、==
比較を行うソートされていないベクトルと、(私が正しく覚えていれば)ハッシュも格納するソートされていないベクトルです。最初にハッシュを比較してから、文字を比較します。
これらのアルゴリズムの範囲は、O(1)
(unordered_map)からO(n)
(線形検索)までです。
適度なサイズのNの場合、O(n)がO(1)を上回ることがよくあります。これは、ノードベースのコンテナーではコンピューターがメモリ内をより多くジャンプする必要があったのに対し、線形ベースのコンテナーではそうではなかったためと考えられます。
O(lg n)
2つの間に存在します。どのようにしたか覚えていません。
パフォーマンスの違いはそれほど大きくなく、大きなデータセットでは、ハッシュベースのデータセットの方がはるかに優れていました。そのため、ハッシュベースの順序付けされていないマップを使用しました。
実際には、妥当なサイズのnの場合O(lg n)
はO(1)
です。お使いのコンピュータのテーブルに40億のエントリしか置けない場合は、O(lg n)
は、上にで囲まれ32
ます。(lg(2 ^ 32)= 32)(コンピュータサイエンスでは、lgは対数ベース2の省略形です)。
実際には、対数成長係数のためではなく、lg(n)部分がアルゴリズムにある程度の複雑さがあることを意味するため、lg(n)アルゴリズムはO(1)アルゴリズムよりも遅く、その複雑さにより、 lg(n)項からの「成長」のどれよりも大きい定数係数。
ただし、(ハッシュマッピングのような)複雑なO(1)アルゴリズムは、類似またはより大きな定数係数を簡単に持つことができます。
アルゴリズムを並行して実行する可能性。
クラスO(log n)
との例があるかどうかはわかりませんO(1)
が、いくつかの問題では、アルゴリズムの並列実行が簡単な場合に、より複雑なクラスのアルゴリズムを選択します。
一部のアルゴリズムは並列化できませんが、それほど複雑でないクラスです。同じ結果が得られ、簡単に並列化できるが、より複雑なクラスを持つ別のアルゴリズムを考えてみましょう。1台のマシンで実行すると、2番目のアルゴリズムは遅くなりますが、複数のマシンで実行すると、実際の実行時間は次第に短くなり、最初のアルゴリズムは高速化できません。
組み込みシステムにブラックリストを実装しているとしましょう。0〜1,000,000の数値がブラックリストに登録されている可能性があります。これにより、次の2つのオプションが可能になります。
ビットセットへのアクセスは、一定のアクセスが保証されます。時間の複雑さに関しては、最適です。理論的観点と実用的な観点の両方から(非常に低い一定のオーバーヘッドを持つO(1)です)。
それでも、2番目のソリューションを使用することをお勧めします。特に、メモリ効率が向上するため、ブラックリストに登録された整数の数が非常に少ないと予想される場合。
また、メモリが不足している組み込みシステム向けに開発しなくても、1,000,000から1,000,000,000,000の任意の制限を増やして、同じ議論をすることができます。その場合、ビットセットには約125Gのメモリが必要になります。O(1)の最悪の場合の複雑さを保証しても、上司にそのような強力なサーバーを提供するように説得することはできません。
ここでは、O(1)ビットセットよりもバイナリ検索(O(log n))またはバイナリツリー(O(log n))を強く推奨します。そして恐らく、最悪の場合のO(n)の複雑さを持つハッシュテーブルは、実際にはそれらすべてに勝るものです。
ここでの私の答えは、確率行列のすべての行にわたる高速ランダム加重選択は、複雑度O(m)のアルゴリズムが複雑度O(log(m))のアルゴリズムよりも高速で、m
大きすぎない場合の例です。
人々はあなたの正確な質問にすでに答えているので、ここに来るときに人々が実際に考えているかもしれない少し異なる質問に取り組みます。
「O(1)時間」アルゴリズムとデータ構造の多くは、実際には予想される O(1)時間のみを使用します。つまり、平均実行時間はO(1)であり、特定の仮定の下でのみ可能です。
一般的な例:ハッシュテーブル、「配列リスト」の拡張(別名動的サイズの配列/ベクトル)。
このようなシナリオでは、平均してパフォーマンスが低下する場合でも、対数的に絶対的に制限されていることが保証されているデータ構造またはアルゴリズムを使用することをお勧めします。
したがって、例として、実行時間は平均で最悪ですが、最悪の場合はより良いバランスのとれた二分探索ツリーが考えられます。
より一般的な質問は、無限に向かう傾向があるとしてもO(f(n))
、O(g(n))
アルゴリズムよりもアルゴリズムを好む状況があるかどうかです。他の人がすでに述べたように、その答えは明らかに「YES」の場合はあると。多項式であるが指数関数的である場合でさえ、それは時々イエスです。有名で重要な例は、線形計画問題を解くためのシンプレックスアルゴリズムの例です。1970年代にはそれが示されました。したがって、その最悪の場合の動作は実行不可能です。しかし、その平均的なケースの振る舞いは、何万もの変数や制約がある実際的な問題であっても、非常に優れています。1980年代には、多項式時間アルゴリズム(このようなg(n) << f(n)
n
f(n) = log(n)
g(n) = 1
f(n)
g(n)
O(2^n)
法の Karmarkarの内点法アルゴリズム)線形計画法が発見されましたが、30年後、シンプレックスアルゴリズムは依然として最適なアルゴリズムのようです(特定の非常に大きな問題を除いて)。これは、平均的なケースの振る舞いが悪いケースの振る舞いよりもしばしば重要であるという明白な理由のためですが、シンプレックスアルゴリズムが何らかの意味でより有益である(たとえば、感度情報が抽出しやすい)より微妙な理由もあります。
私の2セントを入れるには:
アルゴリズムが特定のハードウェア環境で実行されるときに、より複雑なアルゴリズムがより良いアルゴリズムの代わりに選択されることがあります。O(1)アルゴリズムが非常に大きな固定サイズの配列のすべての要素に非順次的にアクセスして問題を解決するとします。次に、そのアレイを機械的なハードドライブまたは磁気テープに配置します。
その場合、O(logn)アルゴリズム(ディスクに順次アクセスする場合)がより有利になります。
他の多くの回答が無視したO(1)アルゴリズムの代わりにO(log(n))アルゴリズムを使用する良いユースケースがあります:不変性。ハッシュマップはO(1)のputsとgetsを持ち、ハッシュ値の分布が適切であると想定していますが、変更可能な状態が必要です。不変のツリーマップにはO(log(n))のputsとgetsがあり、漸近的に遅いです。ただし、不変性はパフォーマンスの低下を補うのに十分な価値がある場合があり、マップの複数のバージョンを保持する必要がある場合は、不変性によりマップをコピーする必要がなくなるため、O(n)となり、したがって改善することができます。パフォーマンス。
単に:係数(そのステップのセットアップ、ストレージ、および実行時間に関連するコスト)は、大きな問題よりも小さなBig-O問題の方がはるかに大きくなる可能性があるためです。Big-Oは、アルゴリズムのスケーラビリティの単なる尺度です。
量子力学の複数の世界の解釈に依存するソートアルゴリズムを提案する、ハッカーの辞書からの次の例を検討してください:
- 量子プロセスを使用してランダムに配列を並べ替え、
- 配列がソートされていない場合は、ユニバースを破棄してください。
- 残りのすべてのユニバースがソートされます(現在のユニバースを含む)。
(ソース:http : //catb.org/~esr/jargon/html/B/bogo-sort.html)
このアルゴリズムのビッグOはであることに注意してください。これはO(n)
、一般的なアイテムでこれまでに知られているすべてのソートアルゴリズムより優れています。線形ステップの係数も非常に低くなっています(線形に行われるのは、スワップではなく比較だけなので)。実際、同様のアルゴリズムを使用して、多項式時間でNPとco-NPの両方の問題を解決できます。可能な解決策(または解決策がないことの証明)は、量子プロセスを使用して生成でき、多項式時間。
ただし、ほとんどの場合、Multiple Worldsが正しくない可能性があるというリスクを冒したくはないでしょう。言うまでもなく、ステップ2を実装する行為は、依然として「読者のための演習として残されています」。
nが制限されていて、O(1)アルゴリズムの定数乗数がlog(n)の制限よりも高い任意の時点。 たとえば、ハッシュセットに値を格納することはO(1)ですが、ハッシュ関数の高価な計算が必要になる場合があります。データアイテムを(ある順序に関して)簡単に比較でき、nの境界がlog nが1つのアイテムのハッシュ計算よりも大幅に少ない場合、バランスのとれたバイナリツリーに格納する方が、ハッシュセット。
すでに良い答えを追加します。実用的な例は、postgresデータベースのハッシュインデックスとBツリーインデックスです。
ハッシュインデックスはハッシュテーブルインデックスを形成してディスク上のデータにアクセスしますが、btreeはその名のとおり、Btreeデータ構造を使用しています。
Big-O時間では、これらはO(1)対O(logN)です。
実際の状況では、特にデータベースシステムでは、ハッシュインデックスは現在推奨されていません。衝突なしにハッシュを達成することは非常に困難であり(O(N)最悪のケースの複雑さにつながる可能性があります)、このため、作成はさらに困難ですそれらは安全にクラッシュします(書き込み先行ロギングと呼ばれます-postgresではWAL)。
O(logN)はインデックスに対して十分であり、O(1)の実装はかなり難しく、時間差は実際には問題にならないため、このトレードオフはこの状況で行われます。
または
これは、誰かが問題に対する回答をあまりにも早く取得できないようにするために、アルゴリズムがわざと遅い問題を設計したいセキュリティアプリケーションの場合によく見られます。
ここに私の頭の上のいくつかの例があります。
O(2^n)
時間内に解読されるように設計されておりn
、キーのビット長はどこですか(これはブルートフォースです)。CSの他の場所では、クイックソートがO(n^2)
最悪のケースですが、一般的なケースはO(n*log(n))
です。このため、アルゴリズムの効率を分析するときに気にするのは、「Big O」分析だけではありません。
O(log n)
アルゴリズムよりもアルゴリズムを好むO(1)
...