1. find middle element
  2. find first element
  3. find last element
  4. not found
  5. single element match
  6. single element not found
  7. large sorted array
コース一覧
コンピューターサイエンス入門:理論編
二分探索 (O(log n))

コンピューターサイエンス入門:理論編

2 進数、論理演算、ビット演算、データ構造、計算量、メモリモデルなど、プログラミングの土台となるコンピュータサイエンスの理論知識を学べるコースです。プログラミングを始めたばかりの学習者や、CS の体系的な土台を作りたい現役エンジニアを対象としています。約 13 時間 (1 日 30 分 × 26 日) で 53 レッスンを修了でき、修了後はコードのパフォーマンスや設計判断の根拠を理解した上で実装できるようになります。

1
2進数とビット演算
01. 2進数から10進数への変換5分
02. 10進数から2進数への変換5分
03. ビットAND演算でフラグ判定5分
04. OR / XOR でフラグを操作する5分
05. popcount で 1 のビット数を数える5分
06. シフト演算で 2 倍 / 半分5分
07. 16 進数から 10 進数への変換5分
08. 第 1 章まとめクイズ5分
2
文字コードと真偽値ロジック
01. 文字 → ASCII コード5分
02. コード → 文字5分
03. UTF-8 のバイト長を返す5分
04. AND / OR の真理値表5分
05. NOT / XOR の真理値表5分
06. 含意 (→) を AND/OR/NOT で表現5分
07. ド・モルガンの法則5分
08. 第2章まとめクイズ5分
3
計算量とBig-O
01. forループの実行回数を返す5分
02. 入れ子ループの実行回数5分
03. 線形探索 (O(n))5分
04. 二分探索 (O(log n))5分
05. バブルソート5分
06. 配列の最大と最小5分
07. 累積和で範囲合計5分
08. 第3章まとめクイズ5分
4
データ構造 (基本)
01. スタック (push/pop) を実装する5分
02. キュー (enqueue / dequeue) を実装する5分
03. カッコのバランス判定 (スタック応用)5分
04. set で重複を除去する5分
05. map で出現回数を数える5分
06. 二数の和 (map で O(n))5分
07. アナグラム判定5分
08. 第 4 章クイズ — データ構造 (基本)5分
5
ファイル / メモリ / IO 概念
01. バイト → KB 変換5分
02. ディスクサイズフォーマット5分
03. キャッシュヒット率5分
04. LRU 簡易シミュレーション5分
05. エンディアンの入れ替え (uint32)5分
06. バッファ範囲チェック5分
07. 第5章まとめクイズ5分
6
ネットワークと符号化
01. Base64 エンコード後の長さ計算5分
02. URL エンコード対象文字数5分
03. IPv4 アドレスを 32bit 整数に変換5分
04. 32bit 整数を IPv4 アドレスに変換5分
05. CIDR プレフィックスからネットマスクを作る5分
06. 単純チェックサム5分
07. 第6章まとめクイズ5分
7
設計と DB 基礎
01. 重複データを 1NF に変換 (フラットなリスト化)5分
02. キーで join (map 利用)5分
03. 残高転送のトランザクション風処理5分
04. CAP の availability 模擬5分
05. URL ルーティング5分
06. 疎結合と密結合 — 依存性注入で設計を変える12分
07. コース総まとめクイズ5分

二分探索 (O(log n))

二分探索の絞り込み

100 万件を、20 回で当てる

前回の線形探索は、100 万件なら最悪 100 万回比べます。ところが配列が小さい順に並んでいるだけで、同じ探索が 20 回 で終わります。回数を 5 万分の 1 にする仕掛けが二分探索です。

種明かしは、1 から 100 までの数を当てるゲームと同じです。「50 より大きいですか」と聞けば、答えが「はい」でも「いいえ」でも候補は半分消えます。次は 25 か 75 を聞く。1 から順に「1 ですか」「2 ですか」と聞く人はいません。

半分に割るたび、候補はこう減る

候補が 100 件だったとして、真ん中を 1 回見るたびに残る件数は次のように減ります。

見た回数残る候補
0 回100
1 回50
2 回25
3 回13
4 回7
5 回4
6 回2
7 回1

7 回で 1 件まで絞れました。これが log2(100) がおよそ 7 だ、という意味です。件数が 100 万でも、同じ数え方で 20 回です。

Python

n = 1000000 steps = 0 while n > 1: n //= 2 steps += 1 print(steps) # 20

件数を 1000 倍にしても、回数は 10 増えるだけです。O(log n) はこういう増え方をします。

並んでいないと、半分を捨てられない

この速さは「真ん中より大きいのだから、左半分には絶対に無い」という判断に丸ごと乗っています。並んでいない配列で同じ判断をすると、平気で存在する値を見落とします。使う前に、その配列が昇順に並んでいるかを必ず確かめてください。

真ん中の位置を出すときは、整数の割り算を使います。

Python

print(7 / 2) # 3.5 print(7 // 2) # 3

3.5 番目という位置は存在しないので、小数のままではインデックスに使えません。JavaScript には整数の割り算が無いので、切り捨てを自分で書きます。

JavaScript

console.log(Math.floor(7 / 2)); // 3

範囲が縮まないと、いつまでも終わらない

二分探索でいちばん多い事故は、答えを間違えることではなく 終わらない ことです。真ん中を見て候補を絞ったつもりが、範囲の端が 1 つも動いていない、という書き方をすると、同じ場所を永遠に見続けます。1 周まわるごとに範囲が確実に狭くなっているか、手を止めて確かめてください。

もう 1 つは、候補が 1 件だけ残った状態を見ずに終わってしまうことです。1 件残っているなら、それはまだ調べていない 1 件です。[42] のような 1 件だけの配列を渡してみると、この取りこぼしにすぐ気づけます。

要件

  1. 二分探索 (左右の境界を毎回半分に縮める) で実装すること
  2. 見つかった場合はそのインデックスを、見つからない場合は -1 を返す
  3. 配列は昇順ソート済みであることを前提として良い

入出力例

binarySearch([1,3,5,7,9,11,13], 9) → 4 binarySearch([1,3,5,7,9], 1) → 0 binarySearch([1,3,5,7,9], 9) → 4 binarySearch([1,3,5,7,9], 6) → -1 binarySearch([42], 42) → 0 binarySearch([42], 7) → -1 binarySearch([2,4,6,8,10,12,14,16,18,20], 14) → 6

ヒント

left = 0, right = len(arr) - 1 で初期化し、while left <= right の間ループ

mid = (left + right) // 2 で中央のインデックスを取る (Python は //、JS は Math.floor)

arr[mid] と target を比較して、left = mid + 1 か right = mid - 1 で範囲を縮める

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

関連レッスン

  • バブルソート

    隣り合う要素を比較・交換していくバブルソートを実装し、O(n^2) の整列アルゴリズムを体感する。

  • 配列の最大と最小

    配列の最大値と最小値を 1 回のスキャンで求める。O(n) で全要素を見る典型例。

  • 累積和で範囲合計

    累積和 (prefix sum) を作っておくことで、範囲合計のクエリを O(1) で答えられる仕組みを学ぶ。

  • 第3章まとめクイズ

    計算量と Big-O、線形探索・二分探索・累積和の理解度を 1 問のクイズで確認する。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • 線形探索先頭から順に1つずつ照合する探索
  • 配列サイズ固定の同型データの集まり
  • 二分探索中央と比較して半分ずつ範囲を狭める探索
  • 判断YES/NO 分岐を表す菱形
  • インデックスDB 検索を速くする索引
  • JavaScriptWeb で動的な振る舞いを担う言語
main.py
学習モード
エディタを読み込んでいます

メモ

二分探索 (O(log n))

⌘S で保存