アルゎリズムの耇雑性分析の抂芁パヌト2

翻蚳者からこのテキストは、材料を過床に「噛む」堎所のために、小さな略語で瀺されおいたす。 著者は、読者には特定のトピックが単玔すぎる、たたは有名すぎるように芋えるかもしれないず正しく譊告しおいたす。 それにもかかわらず、個人的には、このテキストは、アルゎリズムの耇雑さの分析に関する既存の知識を合理化するのに圹立ちたした。 他の誰かに圹立぀こずを願っおいたす。
元の蚘事の量が倚いため、私はそれを郚分に分割したしたが、そのうち合蚈4぀になりたす。
私はい぀ものように翻蚳の品質の改善に関するPMのコメントに非垞に感謝したす。

以前に公開された
パヌト1

難易床


前の郚分から、これらの装食定数をすべお砎棄できる堎合、プログラム呜什をカりントするための関数の挞近的な動䜜に぀いお話すこずは非垞に簡単になるず結論付けるこずができたす。 実際、ルヌプを含たないプログラムにはf( n ) = 1がありたす。この堎合、䞀定数の呜什が必芁なためですもちろん、再垰がない堎合-以䞋を参照。 1からnたでの単䞀サむクルは、サむクルの前埌で䞍倉の数のコマンドを実行し、サむクル内の䞀定数の呜什がn回実行されるため、挞近f( n ) = n nを䞎えたす。

そのような考慮事項に導かれるのは、毎回指瀺を読むよりも面倒ではないので、この資料を統合するためのいく぀かの䟋を芋おみたしょう。 次のPHPプログラムはAサむズn配列A特定の倀が含たれおいるかどうかを確認したす。

 <?php $exists = false; for ( $i = 0; $i < n; ++$i ) { if ( $A[ $i ] == $value ) { $exists = true; break; } } ?> 

配列内の倀を芋぀けるこの方法は、 線圢怜玢ず呌ばれたす 。 プログラムにはf( n ) = nがあるため、これは有効な名前ですより正確には「線圢」を意味したす。次のセクションで怜蚎したす。 break䜿甚するず、1回の反埩の埌でも、プログラムをより早く終了できたす。 ただし、配列A特定の倀がたったく含たれおいない最も䞍利なシナリオに関心があるこずを思い出しおください。 したがっお、 f( n ) = nは以前ず同じです。

挔習2
最も有害な堎合に䞊蚘のPHPプログラムに必芁な呜什数を䜓系的に分析し、その挞近性を導き出したす最初の郚分でJavascriptでプログラムを分析した方法ず同様。 f( n ) = nになるはずです。


配列から2぀の倀を远加し、その結果を新しい倉数に曞き蟌むPythonプログラムを芋おみたしょう。

 v = a[ 0 ] + a[ 1 ] 

ここには䞀定数の呜什があるため、 f( n ) = 1です。

次のC ++プログラムはAサむズnベクトル元の配列 A 2぀の同䞀の倀が含たれおいるかどうかを確認したす。

 bool duplicate = false; for ( int i = 0; i < n; ++i ) { for ( int j = 0; j < n; ++j ) { if ( i != j && A[ i ] == A[ j ] ) { duplicate = true; break; } } if ( duplicate ) { break; } } 


ネストされた2぀のサむクルは、 f( n ) = n 2の圢の挞近を䞎えたす。


実甚的な掚奚事項 単玔なプログラムは、ネストされたサむクルの数をカりントするこずで分析できたす。 n回の繰り返しでの単䞀サむクルにより、 f( n ) = nたす。 ルヌプ内のルヌプはf( n ) = n 2です。 サむクル内のサむクル内のサむクルはf( n ) = n 3です。 などなど。


ルヌプ本䜓のプログラムで関数が呌び出され、その䞭で実行された呜什の数がわかっおいる堎合、プログラム党䜓のコマンドの総数を簡単に刀断できたす。 䟋ずしお次のCコヌドを怜蚎しおください。
 int i; for ( i = 0; i < n; ++i ) { f( n ); } 

f( n )が正確にn呜什を実行するこずがわかっおいる堎合、 f( n )はn回呌び出されるため、プログラム党䜓の呜什数は挞近的にn 2に近づくず蚀えたす。


実甚的な掚奚事項 䞀連のforルヌプが連続しおいる堎合、プログラムの挞近的な動䜜がそれらの䞭で最も遅いルヌプを決定したす。 1぀に続く2぀のネストされたルヌプは、ネストされたルヌプ自䜓ず挞近的に同じです。 ネストされたルヌプは、単䞀ルヌプを支配するず蚀われおいたす。


次に、理論家が䜿甚する興味深い衚蚘法に切り替えたしょう。 fの正確な挞近性を芋぀けるず、プログラムはΘ( f( n ) )ず蚀いたす。 たずえば、䞊蚘の䟋では、プログラムΘ( 1 ) 、 Θ( n 2 )およびΘ( n 2 )がそれぞれプログラムです。 Θ( n ) 「theta from n」 Θ( n )発音されたす。 f( n ) 定数を含む呜什をカりントする元の関数はΘ( - )ず蚀うこずもありたす。 たずえば、 f( n ) = 2nはΘ( n )関数であるず蚀えたす。 䞀般的に、新しいものは䜕もありたせん。 たた、 2n ∈ Θ( n )ず発音するこずもできたす。これは「two nはthen from the n」に属したす。 このような衚蚘法ず混同しないでください。プログラムに必芁なコマンドの数を数えお2nにするず、このアルゎリズムの挞近的な動䜜はn 定数を砎棄するこずでわかりたすずしお蚘述されおいるだけです。 この衚蚘法を䜿甚しお、いく぀かの真の数孊的ステヌトメントを瀺したす。
  1. n 6 + 3n∈Θn 6 
  2. 2 n + 12∈Θ2 n 
  3. 3 n + 2 n∈Θ3 n 
  4. n n + n∈Θn n 

ずころで、最初のパヌトの1぀を実行するこずにした堎合、これは圌の正解です。

この関数぀たりΘ( )を蚘述するものを時間の耇雑さ 、たたは単にアルゎリズムの耇雑さず呌びたす。 したがっお、 Θ( n )アルゎリズムの耇雑さはnです。 Θ( 1 ) 、 Θ( n ) 、 Θ( n 2 )およびΘ( log( n ) )にも特別な名前がありΘ( log( n ) ) 。これらは非垞に䞀般的です。 圌らは、 Θ( 1 )は䞀定時間アルゎリズム、 Θ( n )は線圢 、 Θ( n 2 )は2次 、 Θ( log( n ) )は察数であるず蚀いたす䜕がわからなくおも心配しないでくださいΘ( log( n ) )察数-これに぀いおはすぐに説明したす。


実甚的な掚奚事項  Θが倧きいプログラムは、 Θが小さいプログラムよりも実行が遅くなりたす。



「big O」ずいう衚蚘


実際には、䞊蚘で怜蚎した方法でアルゎリズムの正確な動䜜を芋぀けるのは難しい堎合がありたす。 特に耇雑な䟋の堎合。 しかし、私たちのアルゎリズムの振る舞いは決しお境界を越えるこずはありたせん。 これにより、定数を無芖しおも以前のようにアルゎリズムの速床が明確に瀺されない堎合があるため、䜜業が楜になりたす。 必芁なのはこの境界を芋぀けるこずであり、その方法は䟋で説明する方が簡単です。

孊習アルゎリズムで䜿甚される最もよく知られおいるタスクは゜ヌトです。 サむズnの配列A n おなじみのように聞こえたすか。そしお、それを゜ヌトするプログラムを曞くように求められたす。 ここでの関心は、そのような必芁性が実際のシステムでしばしば生じるこずです。 たずえば、ファむルブラりザヌは、ナヌザヌがファむルを簡単にナビゲヌトできるように、ファむルを名前で䞊べ替える必芁がありたす。 たたは別の䟋ビデオゲヌムでは、仮想䞖界でのプレむダヌの芖点からの距離に応じお、画面に衚瀺されおいる3Dオブゞェクトを䞊べ替えるタスクが発生する堎合がありたす。 目的それらのうちのどれが圌に芋え、どれが芋えないかを決定したすこれは可芖性問題ず呌ばれたす。 ゜ヌトも興味深いものです。なぜなら、゜ヌトには倚くのアルゎリズムがあり、そのいく぀かは他のものよりも悪いからです。 このタスクは、定矩ず説明も簡単です。 それでは、配列を゜ヌトするコヌドを曞きたしょう。

 b = [] n.times do m = a[ 0 ] mi = 0 a.each_with_index do |element, i| if element < m m = element mi = i end end a.delete_at( mi ) b << m end 

Rubyで配列の䞊べ替えを実装する完党に非効率的な方法を次に瀺したす。 もちろん、Rubyは、䜿甚すべき組み蟌み関数を䜿甚した配列の゜ヌトをサポヌトしおいたす。これらは、説明のためだけに瀺した䞊蚘のコヌドよりも間違いなく高速です。

このメ゜ッドは、遞択による゜ヌトず呌ばれたす 。 たず、配列の最小芁玠が怜出され䞊蚘のコヌドではa 。最小倀はm 、そのむンデックスはmiずしお瀺されたす、新しい配列の最埌に配眮されこの堎合はb 、元の配列から削陀されたす。 次に、残りの倀の䞭で、最小倀が再び怜出され、新しい配列珟圚2぀の倀を含むに远加され、叀い配列から削陀されたす。 すべおの芁玠が元の配列から新しい配列に転送されるたで、このプロセスが繰り返されたす。これは、゜ヌトの終了を意味したす。 この䟋では、2぀のネストされたルヌプがありたす。 倖偎のルヌプはn回「実行」され、内偎のルヌプは配列a各芁玠に察しお1回実行されたす。 最初にaはn芁玠があり、各反埩でそれらの1぀を削陀しおから、最初に内郚ルヌプがn回スクロヌルし、次にn - 1 、 n - 2など、最埌の反埩たで内郚ルヌプが1回だけ通過したす。

合蚈1 + 2 + ... + (n - 1) + nを考慮するず、このコヌドの耇雑さを芋぀けるのはやや問題になりたす。 しかし、それに察する「䞊限」を芋぀けるこずができたす。 これを行うには、プログラムを倉曎しおコヌドに觊れるこずなく粟神的にできたす、それを悪化させおから、䜕が起こったかの耇雑さを導き出したす。 そうすれば、元のプログラムの動䜜がひどく、たたはほずんどの堎合良くなっおいるず自信を持っお蚀うこずができたす。

次に、プログラムの耇雑さの結論を単玔化するために、プログラムを倉曎する方法に぀いお考えおみたしょう。 忘れないでくださいそれを悪化させるたずえば、コヌドに新しい呜什を远加するだけで、元のプログラムに察しお評䟡が意味を持぀ようにするこずができたす。 明らかに、プログラムの内郚ルヌプを倉曎しお、各反埩でn回評䟡を匷制するこずができたす。 これらの繰り返しのいく぀かは圹に立たないでしょうが、結果のアルゎリズムの耇雑さを分析するのに圹立ちたす。 この小さな倉曎を行うず、新しいアルゎリズムにはΘ( n 2 )が含たれたす。これは、それぞれが正確にn回実行される2぀のネストされたルヌプを取埗するためです。 もしそうなら、元のアルゎリズムにはO( n 2 )たす。 O( n 2 ) 「 nからの倧きなOの2乗」 )発音されたす。 これは、プログラムが挞近的にn 2より悪くないこずを瀺唆しおいたす。 圌女は良くも良くも働くでしょう。 ずころで、コヌドに実際にΘ( n 2 )堎合、それはただO( n 2 )であるず蚀いたす。 これをよりよく理解するために、元のプログラムを倉曎しおもそれほど倉わらず、ほんの少しだけ悪くなるず想像しおください。 無駄な呜什をプログラムの先頭に远加するようなもの。 これは、呜什カりント関数の定数のみを倉曎したすが、挞近では無芖したす。 したがっお、プログラムのΘ( n 2 )もO( n 2 )です。

しかし、その逆は必ずしも真実ではありたせん。 たずえば、 Θ( n )持぀コヌドΘ( n ) 、 O( n )に加えおO( n )たす。 Θ( n )プログラムがn回実行さfor単なるforルヌプであるず想像するなら、別のfor insideを远加し、 n回繰り返すこずで悪化させるこずができたす。 これにより、 f( n ) = n 2のプログラムが埗られたす。 芁玄 Θ( a )持぀プログラムは、 bよりもb O( b )ほど悪いO( b )です。 たた、倉曎は意味をなさないか、元のコヌドに䌌たコヌドを䜜成する必芁がないこずに泚意しおください。 圌に必芁なのは、䞎えられたnに関しお呜什の数を増やすこずだけです。 結果を䜿甚しお、問題を解決するのではなく、指瀺をカりントしたす。

したがっお、プログラムにO( n 2 )があるず蚀っおも、安党です。アルゎリズムの分析により、 n 2よりも悪くなるこずはありたせんでした。 これにより、プログラムの速床を適切に芋積もるこずができたす。 新しい衚蚘でより良くなるように、いく぀かの䟋を解いおみたしょう。

挔習3
次のうち、正しいものはどれですか
  1. Θ( n )のアルゎリズムにはO( n )
  2. Θ( n )のアルゎリズムにはO( n 2 )
  3. Θ( n 2 )のアルゎリズムにはO( n 3 )
  4. Θ( n )のアルゎリズムにはO( 1 )
  5. O( 1 )のアルゎリズムにはΘ( 1 )
  6. O( n )のアルゎリズムにはΘ( 1 )


解決策
  1. 元のプログラムにはΘ( n )があるため、真です。 したがっお、プログラムを倉曎せずにO( n )を実珟できたす。
  2. n 2は nよりも悪いので、これは本圓です
  3. n 3は n 2より悪いので、これは本圓です
  4. 1 nより悪くないので、これは嘘です。 プログラムがn呜什線圢数を挞近的に䜿甚する堎合、 1 定数の呜什のみを挞近的に必芁ずするように悪化させるこずはできたせん。
  5. 䞡方の困難は同じであるため、本圓です。
  6. それは本圓かもしれないし、そうでないかもしれたせん、それはアルゎリズムに䟝存したす。 䞀般的な堎合、これは嘘です。 アルゎリズムがΘ( 1 )堎合、それは確かにO( n )です。 ただし、 O( n )堎合、 Θ( 1 )ではない可胜性がありたす。 たずえば、 Θ( n )はO( n )ですが、 Θ( 1 )はそうではありたせん。




挔習4
算術玚数のメンバヌの合蚈を䜿甚しお、䞊蚘のプログラムがO( n 2 )だけでなくΘ( n 2 )でもあるこずを蚌明したす。 等差数列がわからない堎合は、 りィキペディアをご芧ください -難しくありたせん。


アルゎリズムの耇雑床は、その真の耇雑床の䞊限であるため、順番にΘで衚されるため、 Θが正確な掚定倀を䞎えるず蚀うこずがありたす。 芋぀けた境界が正確でないこずがわかっおいる堎合は、小文字のを䜿甚しおそれを瀺すこずができたす。 たずえば、アルゎリズムがΘ( n )堎合、その正確な耇雑床はnです。 したがっお、このアルゎリズムは同時にO( n )ずO( n 2 )です。 アルゎリズムはΘ( n ) 、 O( n )は境界をより正確に定矩したす。 そしお、 O( n 2 )を( n 2 ) 発音「nの小さなo」ず読みたす)曞くず、境界の非剛盎性を知っおいるこずを瀺すこずができたす。 もちろん、アルゎリズムの動䜜に関する詳现な情報を埗るために、アルゎリズムの正確な境界を芋぀けるこずができる方が良いですが、残念ながら、これは必ずしも簡単ではありたせん。

挔習5
次の境界のどれが厳密で、どれが厳密ではないかを刀断したす。
  1. O( n )を䞊限ずするΘ( n )アルゎリズム
  2. Θ( n 2 ) O( n 3 )が䞊限ずしお芋぀かっ)アルゎリズム
  3. Θ( 1 ) O( n )を䞊限ずしお芋぀けΘ( 1 )アルゎリズム
  4. O( 1 )を䞊限ずしお芋぀けたΘ( n )アルゎリズム
  5. O( 2n )を䞊限ずするΘ( n )アルゎリズム


解決策
  1. この堎合、 Θ耇雑床ずO耇雑床は同じであるため、境界は厳密です
  2. ここで、 O Θよりも倧きいスケヌルの耇雑さであるため、この境界は厳密ではありたせん。 実際、ここでの厳密な境界はO( n 2 )です。 アルゎリズムがo( n 3 )ず曞くこずができるように
  3. 繰り返したすが、 OはΘよりも倧きなスケヌルの耇雑さであり、境界は厳密ではないず結論付けたす。 O( 1 )厳密であり、 O( n )はo( n )曞き換えるこずができたす
  4. この境界は間違っおいるため、この境界の導出に間違いがありたした。 Θ( n ) nは1よりも耇雑なのでΘ( n )アルゎリズムは䞊限O( 1 )持぀こずができたせん。 忘れないでください、 Oは䞊限を瀺したす
  5. 非厳密な境界線があるように芋えるかもしれたせんが、実際にはそうではありたせん。 実際、境界線は厳密です。 挞近2nずnは同じであり、 OずΘは挞近のみに関連付けられおいるこずを思い出しおください。 O( 2n ) = O( n )であるため、耇雑さはΘであるため、境界は厳密です。





実甚的な掚奚事項 アルゎリズムのO耇雑床を芋぀けるこずは、そのΘ耇雑床よりも簡単です。


今では、これらすべおの新しい衚蚘法ず混同されおいるかもしれたせんが、次の䟋に進む前に、さらに2぀の文字を理解したしょう。 䞊蚘で、プログラムを倉曎しお、O衚蚘を䜜成するよりも悪化させたした呜什数を増やし、実行時間を増やしたした。 は、コヌドが特定の制限より遅くなるこずは決しおないこずを教えおくれたす。 これから、評䟡の基瀎が埗られたす。プログラムは十分ですか 反察のこずを行い、既存のコヌドを改善し 、䜕が起こるかの耇雑さを芋぀ける堎合、Ω衚蚘を䜿甚したす。 したがっお、 Ωは耇雑さをもたらしたすが、これはプログラムを改善するこずはできたせん。 プログラムが遅いか、アルゎリズムが悪いこずを蚌明したい堎合に䟿利です。 たた、この特定の堎合に䜿甚するにはアルゎリズムが遅すぎるず蚀う堎合にも䜿甚できたす。 たずえば、アルゎリズムがΩ( n 3 )ずいうこずは、アルゎリズムがn 3より良くないこずを意味したす。 Θ( n 3 ) 、たたはΘ( n 4 ) 、たたはそれより悪い堎合もありたすが、その「良さ」の限界はわかりたす。 したがっお、 Ωは、アルゎリズムの耇雑さの䞋限を瀺したす。 οず同様に、この制限が厳密でないこずがわかっおいる堎合は、 ω曞くこずができたす。 たずえば、 Θ( n 3 )アルゎリズムはο( n 4 )およびω( n 2 )です。 Ω( n ) 「nから倧きいオメガ」 Ω( n )発音され、 ω( n ) 「nから小さいオメガ」 ω( n )発音されたす。

挔習6
次のΘ難易床に぀いおは、厳密なO制限ず厳密でないO制限、および必芁に応じお厳密な制限ず厳密でないΩ制限存圚する堎合を蚘述したす。
  1. Θ1
  2. Θ√n
  3. Θn
  4. Θn 2 
  5. Θn 3 


解決策
これは、䞊蚘の定矩を盎接䜿甚する挔習です。
  1. 厳密な境界はO( 1 )およびΩ( 1 )たす。 非厳密なO境界はO( n )です。 Oには䞊限があるこずを思い出しおください。 nは1より倧きいスケヌルにあるため、これは厳密な制限ではなく、 o( n )曞くこずもできたす。 ただし、 1未満の関数はないため、 Ω厳密でない制限を芋぀けるこずはできたせん。 だから、あなたは厳栌な囜境に察凊する必芁がありたす
  2. 厳密な制限はΘ耇雑床ず同じです。 O√nおよびΩ√n、それぞれ。 非厳密な制限の堎合、 n √nより倧きいためO( n ) nたす。 そしお、この境界は厳密ではないので、 o( n )曞くこずができたす。 䞋の非厳密な境界ずしお、単にΩ( 1 ) たたはω( 1 ) を䜿甚したす
  3. 厳密な制限はO( n )およびΩ( n )です。 非厳密には、 ω( 1 )およびo( n 3 )たす。 どちらも元の耇雑さからはほど遠いので、最高の境界線ではありたせんが、私たちの定矩に合っおいたす
  4. 厳密な境界はO( n 2 )ずΩ( n 2 )です。 非厳密な境界ずしお、前の䟋のようにω( 1 )ずo( n 3 )を䜿甚したす
  5. 厳密な境界は、それぞれO( n 3 )およびΩ( n 3 )です。 2぀の非厳密な境界は、ω√nn2ずo√nn3です。 これらの制限はただ厳密ではありたせんが、䞊蚘で掚枬した制限よりも優れおいたす。




Θ代わりにOずΩを䜿甚する理由は、芋぀かった境界の粟床が䞍明な堎合や、アルゎリズムを深く掘り䞋げたくない堎合があるためです。

さたざたな衚蚘法をすべお芚えおいなくおも心配する必芁はありたせん。 い぀でも戻っお情報を曎新できたす。 最も重芁な文字はOずΘです。

たた、 Ωは関数の動䜜に䞋限を䞎えたす぀たり、プログラムを改善しお呜什の蚈算を少なくするが、最悪の堎合の分析を参照しおいるこずに泚意しおください。 これは、最悪のデヌタセットをプログラムにフィヌドし、その動䜜を分析するためです。

次の衚は、䞊蚘で瀺した蚘号ず、数倀を比范するための通垞の数孊アむコンずの関係をたずめたものです。 通垞の数孊衚蚘の代わりにギリシャ文字を䜿甚する理由は、通垞ではなく挞近掚定倀の比范を扱っおいるこずを瀺す必芁があるからです。

挞近掚定の比范挔算子数倀比范挔算子
アルゎリズムはo 䜕かです数<
O ( - )≀ -
Θ ( - )= -
Ω ( - )≥ -
ω ( - )> -




: , O , o , Ω , ω Θ , O , , Θ , , Ω .

Source: https://habr.com/ru/post/J195482/


All Articles