私は常に次の複雑さを考えました。
1 + 2 + 3 + ... + n
はO(n)であり、2つのn行n列の行列を合計するとO(n ^ 2)になります。
しかし、今日、私は教科書から「最初のn個の整数の合計の式によって、これはn(n + 1)/ 2です」と読み、したがって(1/2)n ^ 2 +(1/2) n、したがってO(n ^ 2)。
ここで何が欠けていますか?
big O表記 は、any関数の成長率を決定するために使用できます。
この場合、本は価値を計算する時間の複雑さについてではなく、価値自体について話しているようです。そしてn(n+1)/2
はO(n^2)
です。
n(n + 1)/ 2は、N整数(1から開始)の連続したシーケンスを合計する簡単な方法です。アルゴリズムをbig-oh表記と混同していると思います。
これを関数と考えた場合、この関数の複雑さはO(1)です。
public int sum_of_first_n_integers(int n){ return(n *(n + 1))/ 2; }
素朴な実装は、O(n)の大規模な複雑さを持ちます。
public int sum_of_first_n_integers(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += n;
}
return sum;
}
行列にはn ^ 2のセルがあるため、単一のn行n列の行列の各セルを見るだけでもO(n ^ 2)です。
runtimeの複雑さとresultのサイズ(複雑さ)を混乱させています。
実行時間次から次への合計、最初のn連続する数値は確かに[〜#〜] o [〜#〜] (ん)。1
しかし、結果の複雑さ、つまり「1から合計n」のサイズ= ん(ん – 1)/ 2は[〜#〜] o [〜#〜](ん ^ 2)。
1 しかし、任意の大きな数の場合、大きな数を追加すると小さな数を追加するよりも時間がかかるため、これは単純化されています。正確なランタイム分析を行うには、実際に結果のサイズを考慮する必要があります。ただし、これは通常プログラミングには関係がなく、純粋に理論的なコンピュータサイエンスにも関係ありません。両方のドメインで、数値の合計は通常、ドメインによって明示的に要求されない限り(つまり、bignumライブラリの操作を実装する場合)、[〜#〜] o [〜#〜](1)操作と見なされます。 。
だから私の推測では、これは実際には Cracking the Coding Interview への参照であり、StringBuffer
の実装に関するこの段落があります。
各連結で、文字列の新しいコピーが作成され、2つの文字列が文字ごとにコピーされます。最初の反復では、
x
文字をコピーする必要があります。 2番目の反復では、_2x
_文字をコピーする必要があります。 3番目の反復には_3x
_が必要です。したがって、合計時間はO(x + 2x + ... + nx)
です。これはO(xn²)
になります。 (なぜそれがO(xnⁿ)
ではないのですか?_1 + 2 + ... n
_はn(n+1)/2
またはO(n²)
と等しいためです。)
なんらかの理由で、これも最初のリードスルーで少し混乱しました。注目すべき重要な点は、n
がn
を乗算している、つまり、_n²
_が発生していて、それが優勢であることです。これが最終的にO(xn²)
がO(n²)
になる理由です。x
は一種の赤いニシンです。
問題の複雑さではなく、アルゴリズムの複雑さがあります。
あなたのケースでは、すべての数値を反復することを選択した場合、複雑さは確かにO(n)
です。
しかし、これは最も効率的なアルゴリズムではありません。より効率的な方法は、定数-n*(n+1)/2
を適用することです。したがって、複雑さはO(1)
です。
追加される数値の数に依存しない数式があるため、これは定数時間アルゴリズム、またはO(1)です。
各数値を一度に1つずつ追加すると、それは確かにO(n)になります。式はショートカットです。これは別の、より効率的なアルゴリズムです。追加される数値がすべて1 ..nの場合、ショートカットは機能します。連続しない数値のシーケンスがある場合、ショートカット式は機能せず、1つずつアルゴリズムに戻る必要があります。
ただし、これは数値のマトリックスには適用されません。 2つの行列を追加する場合でも、n ^ 2個の異なる数値のペアを追加してn ^ 2の結果の行列を取得するため、O(n ^ 2)のままです。
N個の任意の整数を合計することと、すべてが連続するN個を合計することの間には違いがあります。 1 + 2 + 3 + 4 + ... + Nの場合、それらを共通の合計でペアに分割できるという事実を利用できます。 1 + N = 2+(N-1)= 3+(N-2)= ... = N + 1.つまり、N + 1、N/2回です。 (奇数の場合、それらの1つはペアになりませんが、少し努力すれば、同じ式がその場合にも当てはまることがわかります。)
しかし、それはO(N ^ 2)ではありません。 ses N ^ 2、実際にはO(1)という式にすぎません。 O(N ^ 2)は、(大まかに)計算するステップ数がN ^ 2のように大きくなることを意味します。この場合、Nに関係なく、ステップ数は同じです。
一連のn自然の和の答えは、2つの方法で見つけることができます。最初の方法は、ループ内のすべての数値を追加することです。この場合、アルゴリズムは線形で、コードは次のようになります
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += n;
}
return sum;
1 + 2 + 3 + 4 + ...... + nに類似しています。この場合、アルゴリズムの複雑さは、O(n)である加算演算が実行される回数として計算されます。
一連のn個の自然数の和の答えを見つける2番目の方法は、最も近い式n *(n + 1)/ 2です。この式では、繰り返し加算ではなく乗算を使用しています。乗算演算は線形時間の複雑さを持ちません。乗算に使用できるさまざまなアルゴリズムがあり、O(N ^ 1.45)からO(N ^ 2)までの時間の複雑さがあります。したがって、乗算時間の場合、複雑さはプロセッサのアーキテクチャに依存します。しかし、分析のために、乗算の時間の複雑さはO(N ^ 2)と見なされます。したがって、合計を見つけるために2番目の方法を使用すると、時間の複雑度はO(N ^ 2)になります。
ここで、乗算演算は加算演算と同じではありません。だれかがコンピュータ編成の主題の知識を持っている場合、彼は乗算と加算の演算の内部動作を簡単に理解できます。乗算回路は加算回路よりも複雑で、結果を計算するために加算回路よりもはるかに長い時間を必要とします。したがって、シリーズの合計の時間の複雑さは一定ではありません。