線形探索シミュレーター
線形探索(逐次探索)は、配列の先頭から順番に1つずつ値を比べていく、もっとも基本的な探索です。 要素数(4〜10個)と場面を選び、1ステップずつ止めて動きを確認できます。
動きを1ステップずつ確認する
- 比較中
- 不一致
- 一致・記録
- 一致・無視
パソコンではキーボードでも操作できます:→ 次へ / ← 前へ / スペース 再生・一時停止
数値を自分で入力する
カンマ区切りで 0〜99 の整数を入力します。擬似コードの1行目・2行目も自動で同じ内容に変わります。
実行ログを見る(ここまでの処理)
ALGORITHM
線形探索とは何をしているか
線形探索は、配列の先頭(添字 0)から末尾まで順番に進みながら、それぞれの要素を探したい値 target と比べていくアルゴリズムです。
「逐次探索」「順次探索」とも呼ばれます。やっていることは、机の上に並んだカードを左から1枚ずつめくって目的のカードを探す作業とまったく同じです。
処理に必要な部品は3つだけです。どこを見ているかを表す添字 i、見つかった位置を覚えておく変数 pos、そして要素と target を比べる条件式です。
上のシミュレーターで「次へ」を押していくと、この3つがどう変化していくかを1ステップずつ確認できます。
考え方は単純ですが、共通テスト「情報Ⅰ」では 添字 i の進み方・見つからなかったときの値・同じ値が複数あるときの扱い・比較回数が繰り返し問われます。 つまり「なんとなく分かる」では足りず、1行ずつ値を追える状態にしておく必要があります。
なぜ pos の初期値は -1 なのか
配列の添字は 0 から始まります。そのため pos = 0 を初期値にしてしまうと、「先頭の要素が見つかった」場合と「まだ何も見つかっていない」場合を区別できなくなります。
添字としては絶対にあり得ない値である -1 を初期値にしておけば、最後まで pos が -1 のままなら「配列の中に target は存在しなかった」と判断できます。
シミュレーターの「見つからない」プリセットを試すと、最後まで -1 が残る様子が確認できます。
整列されていなくても使える
線形探索の大きな特徴は、配列が小さい順に並んでいなくても正しく動くことです。先頭から全部見ていくのだから、並び方は結果に影響しません。 「整列済みでなければ使えない」という制約があるのは二分探索のほうです。この2つはセットで問われやすいので、前提条件の違いをはっきり区別しておきましょう。
同じ値が複数あるときの扱い
配列に target と同じ値が2つ以上あるとき、「どの位置を答えとするか」は条件の書き方で決まります。シミュレーターの「条件の書き方」を切り替えると、この違いをそのまま比較できます。
| 条件の書き方 | 結果 | 比較回数 |
|---|---|---|
| Nums[i] == target かつ pos == -1 | 最初に見つかった位置 | n 回(最後まで見る) |
| Nums[i] == target で繰り返しを抜ける | 最初に見つかった位置 | 見つかるまで |
| Nums[i] == target(条件なしで代入) | 最後に見つかった位置 | n 回(最後まで見る) |
CODE
3つの書き方で見る線形探索
同じアルゴリズムを、共通テストの擬似言語(DNCL風)・Python・JavaScript で並べました。 変数名と処理の順番はすべて揃えてあるので、言語が変わってもやっていることは同じだと確認できます。
Nums = [4, 9, 2, 9, 6] target = 9 pos = -1 i を 0 から 要素数(Nums) - 1 まで 1 ずつ増やしながら繰り返す: |もし Nums[i] == target かつ pos == -1 ならば: ⎿⎿ pos = i 表示する(pos)
nums = [4, 9, 2, 9, 6]
target = 9
pos = -1
for i in range(len(nums)):
if nums[i] == target and pos == -1:
pos = i
print(pos)
const nums = [4, 9, 2, 9, 6];
const target = 9;
let pos = -1;
for (let i = 0; i < nums.length; i++) {
if (nums[i] === target && pos === -1) {
pos = i;
}
}
console.log(pos);
range(len(nums))、JavaScript の i < nums.length は、
すべて同じ範囲(添字 0 から n-1 まで)を表しています。書き方が違うだけで、末尾を含めて1回ずつ調べる点は共通です。
COST
比較回数と計算量
線形探索の手間は「何回比較したか」で測ります。要素数を n として整理すると次のようになります。 シミュレーターで「先頭にある(最良)」と「末尾にある(最悪)」を切り替え、変数「比較回数」の最終値を見比べてみてください。
| 場合 | どんなとき | 比較回数 | 計算量 |
|---|---|---|---|
| 最良 | target が先頭(添字 0)にある | 1 回 | O(1) |
| 平均 | target が配列のどこかにある | 約 n / 2 回 | O(n) |
| 最悪 | target が末尾にある、または存在しない | n 回 | O(n) |
要素数を変えて確かめる:シミュレーターの「要素数を選ぶ」で 4個 → 10個 と増やしながら「末尾にある(最悪)」を試すと、 最終的な比較回数が 4回 → 10回 と、要素数とぴったり同じだけ増えていくことが確認できます。 「見つからない」を選んだ場合も同じで、要素数と等しい回数になります。この2つが最悪の場合です。
要素数が2倍になれば、かかる手間もおよそ2倍になります。これが O(n)(要素数に比例する)という意味です。 1000個の配列なら最悪1000回、100万個なら最悪100万回の比較が必要です。 一方、整列済みの配列に対して使える二分探索は、1回の比較で候補を半分に減らせるため、100万個でも約20回で済みます。 この差が「整列してから探す」意味につながります。
EXAM POINT
共通テスト「情報Ⅰ」での出題ポイント
線形探索そのものを一から書かせる問題より、穴埋めやトレース(値の追跡)として出るほうが多いです。狙われやすいのは次の5点です。
- 繰り返しの終了値:「0 から 要素数 - 1 まで」の
- 1が空欄になる形。0 から数え始めるので、最後の添字は n ではなく n-1 です。 - 見つからなかったときの値:
pos = -1の初期化や、「-1 のとき何を表示するか」を問う形。 - 条件式の空欄:
Nums[i] == targetの比較演算子や、かつ pos == -1の部分。ここが変わると答えが「最初の位置」か「最後の位置」かで変わります。 - 比較回数を数える:変数
countを増やす行を追加した形。繰り返しを抜ける処理があるかどうかで答えが変わります。 - 添字が1始まりの問題文:「1番目の商品」のように日常の言い方と添字がずれる形。問題文の「〇番目」と配列の添字
iの対応を必ず確認します。
i と pos の欄を作り、1行ずつ値を書き換えていくのが一番確実です。
上のシミュレーターは、その手作業を画面上でやっているだけです。まず自分で予測し、その後シミュレーターで答え合わせすると力がつきます。
MISTAKES
よくある間違い
| 間違い | 何が起きるか | 正しくは |
|---|---|---|
| 繰り返しを「要素数まで」にする | 存在しない添字 n を参照してエラーになる | 「要素数 - 1 まで」にする |
| pos の初期値を 0 にする | 先頭で見つかった場合と見つからない場合を区別できない | 添字にあり得ない -1 を使う |
| 条件に pos == -1 を入れ忘れる | 同じ値が複数あると、最後の位置で上書きされる | 最初の位置が必要なら条件を足す、または繰り返しを抜ける |
| 整列済みでないと使えないと思う | 使える場面で選択肢から外してしまう | 整列が前提なのは二分探索だけ |
| 見つけた後も比較回数を数え続ける | 繰り返しを抜けるコードで比較回数を多く答えてしまう | 抜ける処理があれば、そこで数えるのを止める |
CHECK
理解度チェック
まず自分で考え、答えを開く前に上のシミュレーターで確かめてみてください。
Q1. Nums = [4, 9, 2, 7, 6] で target = 6 のとき、pos と比較回数はいくつになりますか。
Q2. Nums = [4, 9, 2, 9, 6] で target = 9 のとき、条件から「かつ pos == -1」を取り除くと pos はいくつになりますか。
pos = 3 に上書きされます。
結果として「最後に見つかった位置」が残ります。「かつ pos == -1」は最初の位置を守るための条件だと理解しておきましょう。