ふくふくHukuhuku Inc.
EP.15STEM対象: 高1以上 15分公開: 2026-05-10

探索アルゴリズム入門:線形検索からベクトル検索・量子探索まで

「データの中から欲しいものを見つける」ための工夫の歴史。線形 O(n) → 二分 O(log n) → ハッシュ O(1) → BFS/DFS → A* → chatgpt を支えるベクトル検索、そして量子コンピュータの Grover アルゴリズムまで。

#中高生#アルゴリズム#探索#ai
CO📔 Google Colab で開く(上から順にセルを実行)
シェア

「探す」は、コンピュータの仕事の半分を占めると言ってもいいくらい基本的な処理。検索エンジン、、ナビゲーション、 の中身まで、全部「探索」が中心にあります。今回はその発展史を、線形検索から最新のベクトル検索まで、自分で動かしながら追います。

今回のゴール

① 線形 O(n) と二分 の絶望的な差を肌で感じる ② グラフ探索( / )と A* の違い ③ なぜ ChatGPT が「ベクトル検索」を内部で使っているか ④ 量子コンピュータの Grover アルゴリズムは何が嬉しいか

Step 0: なぜ「探す」が問題になるのか

100億ドキュメントから1秒以内に答えを返す Google、200万曲から好みの曲を見つける Spotify、20億トークンから次の単語を予測する ── 全部「探索の効率化」がコアの工夫です。 1946 ─ 線形検索(最初のコンピュータと同時):先頭から順に見るだけ。 1962 ─ 二分検索の体系化(実は古代から):ソート済みなら半分ずつ絞れる。 1953:H.P. Luhn が IBM で発明。O(1) 探索1959 ─ ダイクストラ法:最短経路。1968 ─ A*:ヒューリスティック付き最短経路。 2016(Hierarchical Navigable Small World):高次元ベクトルの近似最近傍探索。 2017〜 ─ ベクトル検索の実用化:(Facebook)、ScaNN(Google)、ChatGPT の など。 1996 ─ Grover アルゴリズム:量子コンピュータで O(√n)。

Step 1: 線形 vs 二分 ─ 計測してみる

ナイーブな線形検索とPython の bisect(二分)
Python
import time, random, bisect
n = 10_000_000data = sorted(random.random() for _ in range(n))target = data[n // 2]   # 中央の値を探す
# 線形(リストの index = O(n))t0 = time.perf_counter()data.index(target)print(f"線形: {time.perf_counter() - t0:.4f} s")
# 二分(O(log n))t0 = time.perf_counter()bisect.bisect_left(data, target)print(f"二分: {time.perf_counter() - t0:.4f} s")
10000倍の差

1000万要素では、線形は数百ms、二分は数µs。これが「アルゴリズム選択」の差。データ構造(ソート済みリスト)と探索方法(二分)はセットで設計する。

Step 2: ハッシュテーブル ─ O(1) で見つける

Python の dictset は内部でハッシュテーブルを使ってます。「キーをハッシュ関数で配列インデックスに変換 → 直接アクセス」で、サイズに関わらず O(1)(衝突無視)。

dict で大量検索
Python
import time, random
n = 10_000_000keys = list(range(n))random.shuffle(keys)d = {k: i for i, k in enumerate(keys)}   # ハッシュテーブル構築
t0 = time.perf_counter()for _ in range(100_000):    _ = d[random.randint(0, n-1)]   # O(1) アクセスprint(f"100,000 回のハッシュ検索: {time.perf_counter()-t0:.3f} s")

Step 3: グラフ探索 ─ BFS / DFS / A*

迷路を解く、地図上で目的地へのルートを探す、 で「友達の友達」を探す ── これら全部 グラフ探索

迷路を BFS で解く
Python
from collections import deque
# 0=通路, 1=壁。S=start, G=goal は座標でmaze = [    [0,0,1,0,0],    [1,0,1,0,1],    [0,0,0,0,0],    [0,1,1,1,0],    [0,0,0,0,0],]start, goal = (0, 0), (4, 4)
def bfs(maze, start, goal):    H, W = len(maze), len(maze[0])    q = deque([(start, [start])])    seen = {start}    while q:        (r, c), path = q.popleft()        if (r, c) == goal:            return path        for dr, dc in [(-1,0), (1,0), (0,-1), (0,1)]:            nr, nc = r+dr, c+dc            if 0 <= nr < H and 0 <= nc < W and maze[nr][nc] == 0 and (nr,nc) not in seen:                seen.add((nr,nc))                q.append(((nr,nc), path + [(nr,nc)]))    return None
path = bfs(maze, start, goal)print("最短経路:", path)
5x5の迷路、BFSで見つけた最短経路が赤線で示されている
BFS は「全方向に等しく広がる」ので、最初に goal に到達した経路が最短
BFS / DFS / A* の使い分け

BFS: 最短経路(重みが等しいとき)。DFS: 深く掘る、解の存在判定。ダイクストラ: 重み付き最短経路。A*: ダイクストラ+ゴール方向のヒューリスティック → ゲームAIや経路探索の標準。

Step 4: ベクトル検索 ─ ChatGPT の中身

意味が近い」を探したい場合、文字列の完全一致では無理。文を ベクトル(数百〜数千次元の数列) に変換し、ベクトル空間で近いものを探す=ベクトル検索。これが LLM の RAG(検索拡張生成)の中核。

簡易ベクトル検索(cosine-similarity)
Python
import numpy as np
# 仮の文書ベクトル(本来は埋め込みモデルで作る)docs = {    "犬は哺乳類": np.array([0.9, 0.1, 0.0, 0.2]),    "猫は哺乳類": np.array([0.85, 0.15, 0.0, 0.25]),    "魚は脊椎動物": np.array([0.1, 0.0, 0.9, 0.05]),    "鳥は脊椎動物": np.array([0.2, 0.0, 0.85, 0.1]),    "石は鉱物": np.array([0.0, 0.9, 0.0, 0.0]),}
def cosine(a, b):    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 「ペット」っぽいクエリベクトルquery = np.array([0.88, 0.12, 0.0, 0.22])
scored = sorted(docs.items(), key=lambda kv: cosine(query, kv[1]), reverse=True)for name, v in scored:    print(f"{cosine(query, v):.3f}  {name}")
HNSW: 100億ベクトルから一瞬で

全ベクトルとの類似度を計算すると O(n) で遅い。HNSW(2016) は「近所の近所を辿るネットワーク」で O(log n) に。FAISS / ScaNN / pgvector / Pinecone など、現代のは全部このアイデアを使っています。

Step 5: 量子探索 ─ Grover アルゴリズム

1996 年、Lov Grover が示した量子探索:ソートされていない n 要素から「条件を満たすもの」を O(√n) で見つけられる。古典コンピュータの O(n) より速い。10億要素なら、古典 10億回 vs 量子 約3万回。

ただし「データを 量子状態 に乗せる」前処理が必要で、現実的な大規模データではほとんど活きません。今のところ研究フェーズ。が、暗号攻撃などで重要視されています(AES の鍵長を実質半分にしてしまう)。

自由研究の提案

① 自分の写真でベクトル検索: 画像を CLIP 等のエンコーダで、好きな写真と「似てる」ものを探す。 ② Wikipedia コーパスで RAG 風: 100記事をベクトル化、自然文の質問に最も関連する記事を返すだけのミニ検索エンジン。 ③ A* で迷路ソルバー: 大きな迷路を生成し BFS と A* で比較。ヒューリスティック関数の作り方で速度が劇的に変わるのを確認。 ④ Bloom Filter / : 「確率的データ構造」── 100% 正確じゃないが、メモリと速度で圧倒的に有利。データ工学の現代標準ツール。

次回予告

EP.16 は計算理論の最先端 問題、近似アルゴリズム、確率的データ構造、そして 2024 年に提示された「Powersort 級の最近の発見」と、量子計算が変えつつある計算可能性の地平。「何が原理的に解けないか」を知ることは、エンジニアの基礎体力です。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp