大O記法の計算例: プログラミングコード

2024-09-13

大O記法の計算と近似方法

大O記法は、アルゴリズムの効率を評価する際に広く使用される数学的な表記です。アルゴリズムの実行時間が入力サイズにどのように依存するかを示します。

大O記法の定義

  • f(n): アルゴリズムの実行時間(通常、操作の数)
  • g(n): 漸近的にf(n)を上界する関数(通常、単純な関数)

f(n) = O(g(n)) と書くと、ある正の定数 c と n₀ が存在し、n ≥ n₀ のとき f(n) ≤ c * g(n) が成り立つことを意味します。

  1. アルゴリズムのステップを特定する:

    • 各ステップの計算量を評価する。
    • 計算量が高いステップに注目する。
    • 計算量が高いステップが支配的となる。
  2. 漸近的に上界する関数を特定する:

    • 合計された計算量を最も単純な関数で上界する。
    • 一般的に、最高次数の項が支配的となる。
  • 最悪ケース: アルゴリズムが最も遅くなる入力の場合を考慮する。
  • 平均ケース: すべての入力に対する平均的な実行時間を考慮する。

  • 線形検索: O(n)
  • 二分検索: O(log n)
  • バブルソート: O(n^2)
  • クイックソート: O(n log n)

計算例: バブルソート

for i = 0 to n-1:
  for j = 0 to n-i-1:
    if arr[j] > arr[j+1]:
      swap(arr[j], arr[j+1])
  • 内側のループは n-i-1 回実行される。
  • 総計算量は O(n^2) となる。



大O記法の計算例: プログラミングコード

線形検索 (Linear Search)

def linear_search(arr, x):
  n = len(arr)
  for i in range(n):
    if arr[i] == x:
      return i
  return -1
  • 最悪ケース: 探索対象の要素が配列の最後にある場合、すべての要素を比較する。
  • 計算量: O(n)
def binary_search(arr, x):
  low = 0
  high = len(arr) - 1
  while low <= high:
    mid = (low + high) // 2
    if arr[mid] == x:
      return mid
    elif arr[mid] < x:
      low = mid + 1
    else:
      high = mid - 1
  return -1   

バブルソート (Bubble Sort)

def bubble_sort(arr):
  n = len(arr)
  for i in range(n):
    for j in range(0, n-i-1):
      if arr[j] > arr[j+1]:
        arr[j], arr[j+1] = arr[j+1], arr[   j]

クイックソート (Quick Sort)

def partition(arr, low, high):
  pivot = arr[high]
  i = low - 1
  for j in range(low, high):
    if arr[j] < pivot:
      i += 1
      arr[i], arr[j] = arr[j], arr[i]
  arr[i+1], arr[high] = arr[high], arr[i+1]
  return i+1

def quic   k_sort(arr, low, high):
  if low < high:
    pi = partition(arr, low, high)
    quick_sort(arr, low, pi-1)
    quick_sort(arr, pi+1   , high)
  • 平均ケース: O(n log n)
  • 最悪ケース: O(n^2)
  • 線形検索: 探索対象の要素が配列の最後にある場合、すべての要素を比較するため、計算量は入力サイズ n に比例する。
  • 二分検索: 配列を半分に分割して検索するため、計算量は対数的に増加する。
  • バブルソート: 内側のループが n-i-1 回実行され、外側のループが n 回実行されるため、計算量は n^2 に比例する。
  • クイックソート: 平均ケースでは、分割がバランスよく行われるため、計算量は n log n に比例する。しかし、最悪ケースでは、分割が不均衡になるため、計算量は n^2 に比例する。



大O記法の計算と近似方法: 他の手法

大O記法の計算と近似方法には、これまで紹介した手法以外にもいくつかのアプローチがあります。以下では、その一部を紹介します。

再帰式を用いた分析

  • 再帰関数: 再帰呼び出しを含む関数
  • 再帰式: 再帰関数の計算量を再帰式で表す
  • マスター定理: 再帰式の解を求めるための定理

例: クイックソート

def quick_sort(arr, low, high):
  if low < high:
    pi = partition(arr, low, high)
    quick_sort(arr, low, pi-1)
    quick_sort(arr, pi+1, high)

再帰式: T(n) = T(n-1) + T(n-2) + O(n)

マスター定理を用いて解くと、T(n) = O(n log n) が得られます。

アムダールの法則

  • 並列処理: タスクを複数のプロセッサで並列実行する
  • 加速比: 並列処理による性能向上率
  • シーケンス部分: 並列化できない部分

例:

  • シーケンス部分の割合が p であるとき、加速比は 1 / (1 - p + p/n) となる。
  • p が小さいほど、並列処理による性能向上効果は大きくなる。

実験的な測定

  • プロファイリングツール: プログラムの実行時間を計測するツール
  • ベンチマーク: 標準的なテストケースを用いた性能評価

実際のプログラムの性能は、アルゴリズムの理論的な計算量だけでなく、実装の詳細やハードウェアの影響も受けます。実験的な測定により、実際の性能を評価することができます。

近似手法

  • 経験則: 過去の経験や知見に基づく推測
  • ヒューリスティック: 厳密な解を求められない場合に近似解を求める手法

大規模な問題や複雑なアルゴリズムの場合、厳密な計算が困難になることがあります。そのような場合、近似手法を用いて大まかな計算量を推定することが有効です。


algorithm optimization complexity-theory

algorithm optimization complexity theory