ホーム第5章: アルゴリズムとデータ構造
第5章 3節

計算量と二分探索

同じ問題を解くにも、アルゴリズム次第で一瞬で終わることもあれば、数日かかることもあります。この効率の良し悪しを数学的に判定する世界共通の基準が計算量です。計算量の読み方を理解し、それを武器にした超高速探索「二分探索」の威力を体感しましょう。

1. アルゴリズムの効率のモノサシ:計算量

アルゴリズムの効率を測るとき、「手元のPCで実行したら 0.5秒だった」という測定の仕方は不適切です。なぜなら、PCの性能(CPUやメモリの速度)やプログラミング言語の種類によって実行時間は変わってしまうからです。

そこで、コンピュータサイエンスでは「処理するデータ数Nが増えたとき、計算ステップ数がどの程度の割合で増加するか」という数学的な評価基準を使います。これが計算量(Computational Complexity)です。

計算量の表記には、O記法(Big-O Notation)を使います。

計算時間 ➔ データ数 N ➔ O(N²) O(N) O(log N) O(1)
図 5-5:データ数Nの増加に伴う各O(オーダー)計算量の増加比較
代表的な計算量(オーダー)の種類
  • O(1):定数時間
    データ数Nに関わらず、常に一定の時間で完了します。例:配列のインデックスアクセス
  • O(log N):対数時間
    Nが倍々で増えても計算時間は微増するだけの、極めて効率のよいオーダーです。例:二分探索
  • O(N):線形時間
    Nの増加に比例して計算時間も増えます。例:線形探索
  • O(N²):二乗時間
    データが少し増えるだけで計算時間が急激に爆発します。Nが10倍になると時間は100倍に。例:単純なソート

2. 線形探索(Linear Search):O(N)

あるデータ群(例えば配列)の中から、目的の値を見つけ出す最も素朴な方法が線形探索(Linear Search)です。

これは、配列の「先頭の要素から末尾に向かって、順番に1つずつ目的の値と一致するかチェックする」という方法です。

最悪の場合、目的のデータが末尾にあるか存在しないため、N回の比較が必要です。よって最悪計算量は O(N) です。

3. 二分探索(Binary Search):O(log N)

検索対象のデータが事前にソート(並び替え)されている場合、圧倒的に高速な二分探索(Binary Search)を使えます。

二分探索の考え方は、辞書で単語を引くときや、数当てゲーム(1〜100の中で数字を当てるゲーム)と全く同じです。

  1. まず、並んでいるデータ群の「ちょうど真ん中の値」を確認します。
  2. 探したいターゲットの値が、その真ん中の値よりも「大きい」か「小さい」かを判定します。
  3. もしターゲットの方が大きければ、真ん中より「左側半分」には絶対にデータはないことが確定するため、探索範囲を「右側半分」に絞り込みます(小さければその逆)。
  4. 絞り込まれた新しい範囲に対して、再びステップ1(真ん中を確認)を繰り返します。
ターゲット: 77 を探す ステップ 1: 56 中央 77 ➔ 77は56より大きいため、左半分を除外 ステップ 2: 除外済み領域 68 77 85 中央 91 ➔ 77は85より小さいため、右半分を除外 ➔ 次で77を発見!
図 5-6:二分探索によって探索範囲が毎ステップ「半分」になる様子

このアルゴリズムの凄さは、探索範囲が毎ステップで半分に縮小していく点にあります。

データ数Nに対する最悪計算回数は、数学的に $\log_2 N$ 回になります。よって、最悪計算量は O(log N) です。

4. O(N) と O(log N) の決定的な速度差

データ数が少ないときは、線形探索 O(N) も二分探索 O(log N) も一瞬で終わり、違いは分かりません。 しかし、データの件数が巨大になったとき、この2つには天と地ほどの差が生まれます。

例えば、日本の全人口(約1億2000万人)の名簿から特定の名前を検索する場合を考えてみます。

  • 線形探索 O(N) の場合:
    最悪で 1億2000万回 の比較ループを実行します。スマホやPCでも、データ読み込みとループ処理で数秒〜数十秒の待ち時間が発生します。
  • 二分探索 O(log N) の場合:
    最悪でもわずか 27回($\log_2 120,000,000 \approx 26.8$)の比較だけで完了します。27回といえば、CPUからすれば一瞬(数ナノ秒)であり、人間には完全にリアルタイム(0秒)で表示されます。

データが数千万倍になっても計算回数は数十回しか増えない。この対数のパフォーマンスこそが、Google検索などの大規模システムを破綻なく高速稼働させる技術的支柱です。

次のセクションでは、直線的な並びではなく、データの親子関係などを網の目のように表現する非線形データ構造「木構造」と「グラフ」について学びます。

現実世界と繋ぐ:アルゴリズムの選択が命運を分ける:数百万人のデータから瞬時に検索する方法

私たちは、スマートフォンの連絡先やSNSのユーザー検索を日常的に使っています。何百万件、何億件ものユーザーデータの中から、1文字入力するだけで結果がその場で瞬時に表示されるのはなぜでしょうか?

  • データベースインデックス: データベースの検索を高速化する「インデックス」と呼ばれる機能は、内部で二分探索を応用したデータ構造(B-Treeなど)を利用しています。あらかじめソートされた形でインデックスが作成されているため、数億件のデータがあっても、わずか数回のデータ比較で目的のレコードに到達できます。
  • 計算量の差がサーバー代を決める: 1回の検索に、線形探索 $O(N)$ を使うとサーバーのCPUはフル稼働し、アクセスが集中するとシステムがダウンしてしまいます。しかし、二分探索 $O(\log N)$ を使用すれば、CPUにかかる負荷は数万分の一に抑えられます。これは、サービスの維持にかかる電気代やサーバーの維持費が何万分の一に激減することを意味します。

プログラムが正しく動くかだけでなく、「どれくらい効率的か(計算量)」を意識する設計こそが、大規模でサクサク動くモダンなWebサービスの設計には欠かせない技術なのです。

整理のポイント:計算量オーダーの大小関係

アルゴリズムの性能評価(O記法)における、代表的な計算量の増加傾向の強さと、二分探索の前提条件を整理しておきましょう。

  • 計算量オーダーの大小関係(効率が良い順)
    • $O(1) < O(\log N) < O(N) < O(N \log N) < O(N^2) < O(2^N)$
    • データ数 $N$ が非常に大きくなると、オーダー間の実行ステップ数は天と地ほどに開きます。
  • 二分探索の前提条件
    • 検索対象のデータが事前にソート(並び替え)されている必要があります。ソートされていないランダムなデータに対しては二分探索を直接適用できず、線形探索を行う必要があります。