この記事について この記事は、生成AIを活用した自動生成フローで作成しています。 JavaScriptの二分探索を、1〜15の架空の数字で1回ずつ追える教材にしました。Math.floorとDOM更新について公式資料を照合し、探索ロジックを15通りの目標値で検査しています。
検証ステータス:🧪 探索ロジック15件確認済み・ブラウザ実機/WordPress表示は未確認
数字を探すとき、最初から1個ずつ調べる代わりに、真ん中を見て候補を半分に減らすのが二分探索です。クリックごとに「今どの数字を見たか」「どの数字を候補から外したか」を観察します。
| 項目 | 今回の条件 |
|---|---|
| 対象 | 現行のPC・スマホ用ブラウザ |
| データ | 昇順の整数1〜15(架空) |
| 操作 | 数字選択・次の比較・リセット |
| 通信・費用 | デモ本体は外部API・CDN不要 |
| 検証範囲 | JSロジックのみ。実画面は未確認 |
まず動かす:数字を半分ずつ絞ろう
二分探索のライブデモを開く(GitHubにHTML/JSソース保存済み。GitHub Pages到達とブラウザ動作は未確認)
スライダーで探す数字を8にします。
「次の比較」を1回押します。
数字8が緑になり、「1回目」「発見しました」と表示される想定です。
画面の青は候補、灰色は除外、黄色は今回の比較、緑は発見です。色だけでなく「比較した履歴」の文章でも結果を確認できます。
GitHubサンプル・READMEにも、ローカルで開く方法と完成コードを置いています。
操作後はここを見る
同じ15個の数字でも、探す位置によって比較回数が変わります。「最初から」を押すか目標を変更して、次の違いを確かめてください。
| 探す数字 | 比較する順番 | 期待回数 |
|---|---|---|
| 8 | 8 | 1 |
| 4 | 8 → 4 | 2 |
| 15 | 8 → 12 → 14 → 15 | 4 |
数字15を探すときは、最初に8を見て「目標は右側」と判断します。次に12、14を見て、最後に15へたどり着きます。左側の1〜7を調べる必要はありません。
観察ポイント:比較回数はいつも同じではありません。今回は15個の整列済みデータなので、どの目標でも最大4回で見つかる設計です。これは実ブラウザでの実測値ではなく、アルゴリズムの期待値です。
なぜ速い? 半分にする仕組み
二分探索は並び順が決まっていることが前提です。昇順の数字なら、真ん中の数字より目標が大きいと分かった時点で、その真ん中より左側は候補から外せます。
flowchart TD
A["中央の数字を見る"] --> B{"目標と同じ?"}
B -->|はい| C["発見"]
B -->|小さい| D["右半分を残す"]
B -->|大きい| E["左半分を残す"]
D --> A
E --> A
この図は考え方の簡略化です。実際のプログラムでは、残す範囲を配列の添字 low と high で管理します。中央の添字を切り捨てで求める部分が重要です。
const mid = Math.floor((low + high) / 2); if (values[mid] < target) low = mid + 1; else if (values[mid] > target) high = mid - 1; else found = true;
Math.floor は小数点以下を切り捨てるため、配列の中央を整数の添字として選べます。+1 と -1 は、すでに比較した中央の数字を次の候補から外すためです。ここを忘れると同じ数字を繰り返し調べるおそれがあります。
15個から始めると候補数は、おおむね15→7→3→1と小さくなります。データ数を増やした場合、必要な比較回数はおおむね log2(N) に比例します。ただし実務では、先に並べ替える時間やデータ更新の頻度も考慮が必要です。
1か所変えて比べよう
最初の目標を8から15へ変え、ほかの条件は変更しないで再実行します。目標変更時は探索履歴がリセットされます。
| 比較 | 目標 | 期待する結果 |
|---|---|---|
| 変更前 | 8 | 1回で発見 |
| 変更後 | 15 | 4回で発見 |
次に「4」を選ぶと2回になります。回数が異なる理由は、配列の中央に近い数字と端にある数字で、半分にする回数が異なるためです。
なお、この教材は最初から1〜15を昇順に並べた固定データです。未整列のリストや同じ値が重複するリストで、同じ結果になるとは限りません。
自分のPCで動かす
GitHubのdocs/demos/binary-search-steps/にあるindex.htmlとapp.jsを同じフォルダへ保存し、index.htmlをブラウザで開きます。外部ライブラリやビルド、APIキーは不要です。
app.jsには、探索の純粋関数、画面の更新、ボタンの処理、変更時のリセットが入っています。記事内には核心だけを載せ、完成コードはGitHubへ分離しました。
うまく動かないとき
| 症状 | まず確認 | 対処 |
|---|---|---|
| ボタンが無反応 | Consoleにエラーがあるか | app.jsの配置を確認 |
| 1回で終わらない | 選んだ目標値 | 8なら1回、15なら4回 |
| 次へ進めない | 発見済みか | 「最初から」で戻す |
| 色が分かりにくい | 比較履歴の文章 | 状態をテキストで確認 |
GitHub Pagesが開かない場合も、URLが存在するはずだと決めつけず、まずREADMEとソースがGitHubにあるかを確認してください。会社・学校のネットワーク制限でPagesが遮断される場合もあります。
仕事・学習で使うなら
商品コードや番号表など、整列済みで値の比較ができるデータから候補を絞る考え方を理解するのに向いています。たとえば1000件の番号を先頭から順番に見る代わりに、中央の値と比較して検索範囲を狭めます。
一方、文章の意味検索、順番が決まっていないデータ、頻繁に更新される小さな一覧では、二分探索だけが最善とは限りません。検索の速さだけでなく、整列と更新の手間も含めて選びます。
探索範囲を毎回更新する理由
二分探索では、今どの数字が候補なのかを毎回管理することが重要です。15個のデータなら最初の候補は1から15までのすべてです。最初に8を比較したとき、目標が15なら右側だけを残します。次に12を比較し、さらに14を見て、最後に15へ進みます。すでに比較した8や12が次の候補から除外されることを画面でも確かめれば、同じ位置を繰り返し調べる不具合を理解できます。目標が4なら、8より左の候補だけが残ることを確認してください。
この手順はデータが昇順に並んでいる前提で成立します。順番がばらばらなリストから中央だけを見て半分を除外すると、探している値を間違って候補から消してしまう可能性があります。商品名の検索なら文字の比較規則を決め、日付の検索なら同じ形式で順番を比べられる状態にする必要があります。元データを並べ替える時間が必要な場合は、その時間も含めて方法を選びます。すでに整列された大量データと、毎回増減する小さな一覧では、適した方法が異なることがあります。
見つからない値と重複する値を考える
今回の教材は1から15の固定データから目標を選ぶため、通常の操作では目標値が存在します。一般的な二分探索を自分で実装する場合は、存在しない値を探したときの終了条件も必要です。候補の最小位置lowが最大位置highを超えたら、これ以上探す場所がないので見つからないと判断します。中央の値を比較して候補を更新するとき、同じ中央を次回も残す設計では、探索が終わらない場合があります。中央を確実に候補から外すことが重要です。
同じ値が複数含まれるリストで二分探索を行う場合、標準的な手順は一致した位置のうちどれか一つを返すことがあります。最初に現れる位置や最後の位置を求めるには、見つかったあとも範囲の境界を探す追加の手順が必要です。今回の1から15には重複がないため、15通りのロジック検査が成功したという記録を、重複データへの対応まで検証した証拠にしてはいけません。検査した条件と未検証の条件を区別することが大切です。
色で候補を分ける場合は、緑が発見、灰色が除外といった意味を色だけに依存させないようにします。比較履歴を文章で示せば、画面の色を見分けにくい人も結果を追えます。実務の検索画面なら、探索中、発見、未発見の状態をそれぞれ文字で伝えると分かりやすくなります。アルゴリズムの数値計算が正しくても、ボタンを押して画面の文字や色が更新される処理は別の検証が必要です。
公式資料
MDN:Math.floor — 中央の添字を整数にする根拠。
MDN:Element.replaceChildren — 候補の画面表示を入れ替える方法。
MDN:changeイベント — 入力変更イベントの説明。本教材は値変更に
inputイベントを利用。
資料確認:2026年11月2日。実際のブラウザ・GitHub Pages到達・WordPress青い囲み・モバイル表示・印刷/PDF・アイキャッチ登録は未確認です。画像は外部から転載せず、デモ内の数字と小さなMermaidで図示します。
GitHubサンプル
二分探索の完成コードとREADME / デモのソース(固定コミット)
本文の引用囲みは既存WordPressのMarkdown変換を想定していますが、青色の実表示は確認していません。Published/Updated/Source/LicenseはWordPressの共通表示に委ね、本文へ重複挿入しません。
