【C++入門】時間計算量の求め方を実例で徹底解説!O(n)からO(n log n)まで
時間計算量(タイム・コンプレキシティ)とは、あるアルゴリズムが処理を完了するまでにかかる時間のことです。アルゴリズムの効率性を示す重要な指標であり、複数のアルゴリズムを比較・分析する際にも用いられます。一般的に、時間計算量を小さく抑えるほど、アルゴリズムはより効率的になります。
本記事では、C++のコードスニペットを題材に、代表的な時間計算量である O(1)、O(n)、O(n²)、O(log n)、O(n log n) を実際のコードから読み解く方法を、5つの例を通じて解説します。
例1:ループ変数が2ずつ増加する場合 → O(n)
次のコードの時間計算量を求めてみましょう。
for(i = 0; i < n; i++){
cout << i << " ";
i++;
}
ループの上限値は n ですが、ループ本体の中でも i がインクリメントされているため、実質的に i は1回の繰り返しごとに2ずつ増加します。その結果、ループが回る回数は約半分になり、処理時間も半分で済みます。したがって、時間計算量は O(n/2) となりますが、定数倍は無視できるため、これは O(n) と同等です。
例2:二重ループの場合 → O(n²)
次のコードの時間計算量を求めてみましょう。
for(i = 0; i < n; i++){
for(j = 0; j < n; j++){
cout << i << " ";
}
}
外側のループと内側のループが、どちらも n 回ずつ実行されます。i の1つの値につき j は n 回ループするため、i が n 通りの値を取る間に、j のループは合計 n × n = n² 回実行されます。したがって、時間計算量は O(n²) です。
例3:値が毎回半分になるループ → O(log n)
次のコードの時間計算量を求めてみましょう。
int i = n;
while(i){
cout << i << " ";
i = i / 2;
}
このケースでは、反復ごとに i の値が前の値の半分になっていきます。したがって、i の値は n, n/2, n/4, n/8, …, 1 というように変化していきます。値が半減しながら1に達するまでに必要な反復回数は log₂n 回程度であるため、時間計算量は O(log n) となります。
例4:条件分岐のみの場合 → O(1)
次のコードの時間計算量を求めてみましょう。
if(i > j){
j > 23 ? cout << j : cout << i;
}
このコードには2つの条件判断が含まれています。それぞれの条件判断の時間計算量は O(1) であり、2つ合計しても O(2) となります。定数倍は無視できるため、これは O(1)、すなわち定数時間と同等です。
例5:外側が線形・内側が対数の二重ループ → O(n log n)
次のコードの時間計算量を求めてみましょう。
for(i = 0; i < n; i++){
for(j = 1; j < n; j = j * 2){
cout << i << " ";
}
}
内側のループは j が2倍ずつ増加するため log n 回実行され、外側のループは n 回実行されます。i の1つの値につき j は log n 回動作するため、i が n 通りの値を取る間に、内側のループは合計 n × log n 回実行されます。したがって、時間計算量は O(n log n) です。
まとめ:計算量パターンの一覧表
| コードのパターン | 時間計算量 |
|---|---|
| 単純なループ(例1) | O(n) |
| 二重ループ(例2) | O(n²) |
| 値が半減するループ(例3) | O(log n) |
| 条件分岐のみ(例4) | O(1) |
| 線形×対数の二重ループ(例5) | O(n log n) |
ビッグオー記法では定数倍や低次の項は無視されるため、「O(n/2)」や「O(2)」のような表記は「O(n)」「O(1)」に簡略化されます。ループ変数の増加パターン(1ずつ増えるか、2倍になるか)とループのネストの深さに注目すれば、多くのコードの時間計算量を直感的に見極められるようになります。ぜひ自分のコードでも試してみてください。
-
漸近解析とは?アルゴリズムの計算量と実行時間の関係を解説
漸近解析(Asymptotic Analysis)とは漸近解析を用いることで、入力サイズに基づいてアルゴリズムの性能をおおよそ把握することができます。ここで重要なのは、正確な実行時間を求めることではなく、実行時間と入力サイズの間にある「関係」を見出すことです。つまり、入力サイズが大きくなるにつれて実行時間がどのように増加していくかに着目して解析を行います。また、空間計算量(スペース複雑性)に関しては、アルゴリズムを完了させるためにメインメモリ上でどれだけの領域が占有されるかを示す関係式や関数を導くことを目標とします。漸近的挙動(Asymptotic Behavior)関数 f(n) の漸近的挙
-
C/C++で実装するバークレーアルゴリズム――分散システムの時刻同期を徹底解説
バークレーアルゴリズムとは バークレーアルゴリズム(Berkeleys Algorithm)は、分散システムにおいて各ノードの時計を同期させるために用いられるアルゴリズムです。特に、以下のような状況にあるシステムで有効とされています。 マシンに正確な時刻源が存在しない場合 ネットワークやマシンにUTCサーバーが用意されていない場合 分散システムとは、物理的に離れた場所に配置された複数のノードが、ネットワークを介して相互に接続されたシステムのことを指します。各ノードの時計は独立して動作しているため、誤差が生じやすく、何らかの同期機構が必要になります。 バークレーアルゴリズムの仕組み このア