【初心者向け】O記法(ビッグオー記法)とは?O(1)、O(n)、O(n²)をわかりやすく解説

テックジム東京本校では、情報科目の受験対策指導もご用意しております。

O記法(オーダー記法)とは

O記法(ビッグオー記法、Big O notation)は、アルゴリズムの**計算量(処理時間やメモリ使用量)**を表現するための数学的記法です。プログラムが「どれくらい速く動くか」「データ量が増えたときにどれくらい遅くなるか」を評価する際に使用されます。

アルゴリズムを選ぶ際や、コードの最適化を行う際に、O記法を理解していることは非常に重要です。

なぜO記法が必要なのか

  • パフォーマンスの予測: データ量が増えたときの処理時間を予測できる
  • アルゴリズムの比較: 複数のアルゴリズムを客観的に比較できる
  • ボトルネックの特定: プログラムの遅い部分を見つけやすくなる

O記法の基本的な読み方

O記法は「O(何か)」という形で表現されます。括弧内の値が、データ量(通常はnで表現)に対する計算量の増加率を示します。

基本的な考え方:

  • n: データの個数やサイズ
  • O(f(n)): データ量nに対する計算量の増加傾向

主要なO記法一覧(速い順)

1. O(1) – 定数時間

特徴: データ量に関係なく、常に一定の時間で処理が完了します。

具体例:

  • 配列の特定位置へのアクセス
  • ハッシュテーブルでの検索(理想的な場合)
  • スタックのpush/pop操作
# O(1)の例:配列の要素へのアクセス
def get_first_element(array):
    return array[0]  # データ量に関係なく即座に取得

グラフのイメージ: 横ばいの直線(どんなにデータが増えても処理時間は変わらない)


2. O(log n) – 対数時間

特徴: データ量が増えても、処理時間の増加は非常に緩やか。データ量が2倍になっても、処理時間はほんの少ししか増えません。

具体例:

  • 二分探索
  • バランスされた二分探索木での検索
# O(log n)の例:二分探索
def binary_search(sorted_array, target):
    left, right = 0, len(sorted_array) - 1
    
    while left <= right:
        mid = (left + right) // 2
        if sorted_array[mid] == target:
            return mid
        elif sorted_array[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1

実際の数値例:

  • n=1000の場合: 約10回の操作
  • n=1000000の場合: 約20回の操作

3. O(n) – 線形時間

特徴: データ量に比例して処理時間が増加します。データが2倍になれば、処理時間も2倍になります。

具体例:

  • 配列の全要素を走査
  • リストの中から特定の値を探す(線形探索)
  • 配列の要素の合計を計算
# O(n)の例:配列内の最大値を探す
def find_max(array):
    max_value = array[0]
    for num in array:  # n回のループ
        if num > max_value:
            max_value = num
    return max_value

実際の数値例:

  • n=1000の場合: 約1000回の操作
  • n=1000000の場合: 約1000000回の操作

4. O(n log n) – 線形対数時間

特徴: O(n)とO(log n)を組み合わせた計算量。効率的なソートアルゴリズムの多くがこの計算量です。

具体例:

  • マージソート
  • クイックソート(平均的な場合)
  • ヒープソート
# O(n log n)の例:マージソート
def merge_sort(array):
    if len(array) <= 1:
        return array
    
    mid = len(array) // 2
    left = merge_sort(array[:mid])    # log n回の分割
    right = merge_sort(array[mid:])
    
    return merge(left, right)  # n回の操作でマージ

5. O(n²) – 二乗時間

特徴: データ量の2乗に比例して処理時間が増加します。データが2倍になると、処理時間は4倍になります。

具体例:

  • バブルソート
  • 選択ソート
  • 挿入ソート
  • 二重ループでの全組み合わせチェック
# O(n²)の例:バブルソート
def bubble_sort(array):
    n = len(array)
    for i in range(n):           # 外側のループ: n回
        for j in range(n - 1):   # 内側のループ: n回
            if array[j] > array[j + 1]:
                array[j], array[j + 1] = array[j + 1], array[j]
    return array

実際の数値例:

  • n=100の場合: 約10000回の操作
  • n=1000の場合: 約1000000回の操作(100倍のデータで100倍の計算量)

6. O(2ⁿ) – 指数時間

特徴: データ量が1増えるだけで処理時間が2倍になる、非常に遅いアルゴリズム。実用的には使えないことが多いです。

具体例:

  • フィボナッチ数列の素朴な再帰実装
  • べき集合の生成
# O(2ⁿ)の例:フィボナッチ数(非効率な実装)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)  # 毎回2つに分岐

実際の数値例:

  • n=10の場合: 約1024回の操作
  • n=20の場合: 約1048576回の操作
  • n=30の場合: 約10億回の操作

O記法の計算量比較表

データ量が増えたときの計算量の増加を比較してみましょう。

データ量(n) O(1) O(log n) O(n) O(n log n) O(n²) O(2ⁿ)
10 1 3 10 30 100 1024
100 1 7 100 700 10000 1.27×10³⁰
1000 1 10 1000 10000 1000000

この表から、O(n²)以上の計算量は大規模データには不向きであることがわかります。


O記法を使った実践的なアルゴリズム選択

検索アルゴリズムの選択

状況: 1000個のデータから特定の値を探したい

アルゴリズム 計算量 データの前提条件 平均操作回数
線形探索 O(n) なし 500回
二分探索 O(log n) ソート済み 10回
ハッシュテーブル O(1) 事前にハッシュテーブル構築 1回

結論: データがソート済みなら二分探索、頻繁に検索するならハッシュテーブルを使うのが効率的です。

ソートアルゴリズムの選択

状況: 10000個のデータをソートしたい

アルゴリズム 計算量 特徴 おすすめ度
バブルソート O(n²) シンプルだが遅い
マージソート O(n log n) 安定で高速
クイックソート O(n log n) 平均的に最速

O記法を理解する上での重要なポイント

1. 定数項は無視する

O記法では、定数倍の差は無視されます。

× O(2n) → ○ O(n)
× O(n/2) → ○ O(n)
× O(100) → ○ O(1)

理由: データ量が十分大きくなれば、定数倍の差は誤差範囲になるため。

2. 最も大きい項だけを残す

複数の項がある場合、最も影響の大きい項だけを残します。

× O(n² + n + 100) → ○ O(n²)
× O(n log n + n) → ○ O(n log n)
× O(2ⁿ + n²) → ○ O(2ⁿ)

3. 最悪ケースを基準にする

O記法は通常、最悪の場合の計算量を表します。

例: クイックソートは平均O(n log n)ですが、最悪ケースではO(n²)になります。


よくある質問(FAQ)

Q1: O(n)とO(2n)は違うの?

A: O記法では同じです。定数倍は無視されるため、どちらも**O(n)**と表記します。

Q2: 空間計算量とは?

A: 時間計算量がアルゴリズムの処理速度を表すのに対し、空間計算量はメモリ使用量を表します。これもO記法で表現できます。

Q3: O(log n)のlogの底は?

A: 通常は底が2ですが、O記法では底が何であっても計算量のオーダーは変わらないため、あまり気にする必要はありません。


まとめ

O記法(ビッグオー記法)は、アルゴリズムの効率性を評価する重要な指標です。

覚えておくべきポイント:

  1. O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ) の順に遅くなる
  2. データ量が大きい場合、O(n²)以上は避けるべき
  3. 定数項は無視し、最も大きい項だけを考える
  4. アルゴリズム選択の際は、データの性質と計算量の両方を考慮する

プログラミングの実践において、O記法を意識することで、より効率的なコードを書けるようになります。特に大規模データを扱う際には、計算量の違いがパフォーマンスに大きく影響するため、適切なアルゴリズムを選択することが重要です。


関連キーワード: 計算量、時間計算量、空間計算量、アルゴリズム、データ構造、ビッグオー、オーダー記法、パフォーマンス最適化、プログラミング効率化

    らくらくPython塾 – 読むだけでマスター

    【現役エンジニア歓迎】プログラミング学習お悩み相談会

    【情報I】受験対策・お悩み相談会(オンライン・無料)

    【オンライン無料】ゼロから始めるPython爆速講座

    テックジム東京本校

    格安のプログラミングスクールといえば「テックジム」。
    講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
    対面型でより早くスキル獲得、月額2万円のプログラミングスクールです。
    情報科目の受験対策指導もご用意しております。