次の関数の実行時間を計算したい
T(n)=(1 + 2 + 3 + 4 + 5 + ... + n)/ n
数式を変換することで簡単に解決できるので、最初はこれは私には難しく見えませんでした
T(n)=(n(n-1)/ 2)/ n =(n ^ 2-n)/ n = n-1これはO(n)につながります。
この機能について考えることで、私は苦労しました。その関数の背後にあるコードがわからないので、nを削減できるかどうかはわかりません。
たとえば、次のようになります
method foo()
{
methodWhichTakesNCubeAmountOfTime(); //Build sum, O(n^2)
methodWhichTakesNAmountOfTimeAndCantBeSimplified(); //O(n)
}
この方法では、ランタイムとしてn個のキューブを取得します。
O(n^2) + O(n) = O(n^2)
私はこれらの方法が元の用語をカバーしていないことを知っていますが、私が意味したことを理解してください:nで割った値は完全に異なる関数である可能性があり(偶然にnの複雑さを持ちます)、したがって、他のnを削減できませんそれで。
だから私は混乱しています。 Big Oの計算中に通常どおり項を変換することはできますか、それとも一部の数学規則はここでは適用されませんか?
ありがとう。
あなただけでなく、それはまさにO-複雑さの定義にあります。
Oの複雑さは、ほとんどの素人プログラマーが理解しているほど単純ではありません。
簡単に言うと、Oは漸近的に定義されます。つまり、nが無限大に近づいた場合のアルゴリズムの動作を理解しようとしていることになります。そして、ほとんどの場合、1つの項が計算を支配します。あなたの例
O(n^2) + O(n) = O(n^2)
それをよく表しています。小さいn
の場合、O(n)
は時間に影響しますが、n
が無限大に近づくと、O(n)
はO(n^2)
と比較して無視できるようになります。したがって、無視しても問題ありません。
これは、Big-Oが1つの用語のみでよく見られる理由でもあります。この項が複雑さの方程式に含まれる場合、n
が無限に近づくにつれて、それが支配的になるためです。
また、1つのメモ。 Big-Oはアルゴリズムのパフォーマンスを測定するための優れた方法ですが、アルゴリズムを評価する実際的な方法というよりは、理論的な数学的ツールにすぎません。
たとえば、2つのアルゴリズムを持つことができます。 1つはO(n^2)
と2つ目はO(1000*n)
です。最初のものはn
が1000より小さい場合に明らかに高速になります。しかし、複雑さを「正しく」するために定数が削除されるため、2番目のものは実際にはO(n)
と記述する必要があります。