私は2つのアルゴリズムを持っていると仮定します:
_for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//do something in constant time
}
}
_
これは当然O(n^2)
です。私も持っていると仮定します:
_for (int i = 0; i < 100; i++) {
for (int j = 0; j < n; j++) {
//do something in constant time
}
}
_
これはO(n) + O(n) + O(n) + O(n) + ... O(n) + = O(n)
です
2番目のアルゴリズムはO(n)
ですが、時間がかかるようです。誰かがこれを拡張できますか?たとえば、最初に並べ替え手順などを実行するアルゴリズムをよく見かけます。全体の複雑さを判断するときは、アルゴリズムを制限する最も複雑な要素です。
はい、O(n)アルゴリズムはO(n2)実行時間に関するアルゴリズム。この定数O(ビッグO表記では省略)が大きい場合に起こります。たとえば、上記のコードでは、O(n)アルゴリズムは定数係数が大きいため、O(nで実行されるアルゴリズムよりもパフォーマンスが低下します。2)n <10の場合.
ここで、n = 100は交差点です。したがって、タスクをO(n)とO(n2)であり、線形アルゴリズムの定数因子は2次アルゴリズムの定数因子よりも大きいため、実行時間がより悪いアルゴリズムを好む傾向があります。たとえば、配列を並べ替える場合、マージ並べ替えまたはクイック並べ替えが漸近的に高速に実行される場合でも、小さい配列の挿入並べ替えに切り替えます。これは、挿入ソートの方がマージ/クイックソートよりも定数係数が小さく、実行速度が速いためです。
Big O(n)
は、異なるアルゴリズムの相対速度を比較するためのものではありません。これらは、入力のサイズが大きくなると実行時間がどれだけ速くなるかを測定するためのものです。例えば、
O(n)
は、n
に1000を掛けると、実行時間が約1000倍になることを意味します。O(n^2)
は、n
に1000を掛けると、ランニングにおよそ1000000が掛けられることを意味します。したがって、n
が十分に大きい場合、O(n)
アルゴリズムはO(n^2)
アルゴリズムに勝ります。固定されたn
に対する何かを意味するものではありません。
簡単に言えば、はい、できます。 O
の定義は、O(f(x)) < O(g(x))
がg(x)
がf(x)
よりも実行に時間がかかることを意味するという事実に基づいています。 x
。
たとえば、小さな値の場合、マージソートは挿入ソートよりも優れているという既知の事実です(正しく覚えていれば、n
が31
)
はい。 O()は漸近的複雑さのみを意味します。線形アルゴリズムは、ループのコアが10回実行されている場合、fe長くなると、2次バージョンのように遅くなります)。
O()-記法は外挿にすぎませんが、非常に良いものです。
得られる唯一の保証は、一定の要因に関係なく、十分な大きさのn
に対して、O(n)アルゴリズムwillO(n ^ 2)よりも少ない操作で済みます。
例として、OPのきちんとした例の操作を数えましょう。彼の2つのアルゴリズムは1行だけ異なります。
for (int i = 0; i < n; i++) { (* A, the O(n*n) algorithm. *)
vs.
for (int i = 0; i < 100; i++) { (* B, the O(n) algorithm. *)
彼の残りのプログラムは同じであるため、実際の実行時間の違いはこれらの2行によって決定されます。
もちろん、O(n)アルゴリズムを高速化するためにnがどれだけ大きくする必要があるかは、定数係数に依存します。定数100
から1000
の場合、カットオフも1000に変わります。