基本情報技術者試験 科目B サンプル問題 問13の解説|2分探索の関数 search が無限ループになる場合

基本情報技術者試験

科目B サンプル問題 問13難易度 ★★★擬似言語・while・2分探索・不具合最終更新 2026-09-22

無限ループ= 止まらずに回り続けること。それが起きる data はどれかを選ぶ問題です。頭の中で理屈を組み立てるより 解答群の4つを、そのまま関数に入れて動かすほうが早い ── 配列はどれも3個までで、1周か2周まわせば判断がつきます。見るのは1周まわったあとの low と high だけ。

難易度 ★★★(当サイトの目安)── 選択肢の入力ごとに探索を追い、無限ループになる場合を探す。4段階の決め方は科目B 最短合格の戦略にあります。

出題

読めない記号があっても大丈夫です。次の節にまとめてあります。

出典:基本情報技術者試験 科目B サンプル問題 問13

次の記述中の    に入れる正しい答えを,解答群の中から選べ。ここで,配列の要素番号は1 から始まる。

関数search は,引数data で指定された配列に,引数target で指定された値が含まれていればその要素番号を返し,含まれていなければ -1 を返す。data は昇順に整列されており,値に重複はない。

関数search には不具合がある。例えば,data の    場合は,無限ループになる。

〔プログラム〕

○整数型: search(整数型の配列: data, 整数型: target)
  整数型: low, high, middle

  low ← 1
  high ← dataの要素数

  while (low ≦ high)
    middle ← (low + high) ÷ 2 の商
    if (data[middle] < target)
      low ← middle
    elseif (data[middle] > target)
      high ← middle
    else
      return middle
    endif
  endwhile

  return -1

解答群

ア 要素数が1 で,target がその要素の値と等しい

イ 要素数が2 で,target がdata の先頭要素の値と等しい

ウ 要素数が2 で,target がdata の末尾要素の値と等しい

エ 要素に-1 が含まれている

答えだけ先に見る

正解は ウ(要素数が2 で,target がdata の末尾要素の値と等しい)です。

この問題に出てくる記号

擬似言語の記号 8コ の読み方をひらく
書き方 読み方
○整数型: search(整数型の配列: data, 整数型: target) ここから関数 search が始まるという印。整数の配列と整数を1つずつ受け取り、整数を1つ返します
整数型: low, high, middle 整数の箱を3つ用意する、という宣言です。中身はまだ決まっていません
← 右の値を、左の箱へ入れるという印。low ← 1 なら「low に 1 を入れる」
data[middle] dataの要素数 配列 data の middle 番目の値/data に入っている値の個数。要素番号は 1 から始まります
while (low ≦ high) endwhile かっこの中が真であるあいだ、endwhile までをくり返す。≦ は「以下」。条件が成り立っていれば真、成り立たなければ偽です
÷ 2 の商 2 で割った答えの整数の部分。7 ÷ 2 は 3.5 ですが、商は 3(小数点以下は切り捨て)
if elseif else endif 上から順に条件を見て、最初に真になった1本だけを実行する。どれも偽なら else の枝へ
return middle return -1 その値を返して、関数をその場で抜ける。あとに何行残っていても実行されません

解答群の4つを、実際に動かして決める

〔プログラム〕はじまりの2行と、くりかえしの中

  low ← 1
  high ← dataの要素数

  while (low ≦ high)
    middle ← (low + high) ÷ 2 の商
    if (data[middle] < target)
      low ← middle
    elseif (data[middle] > target)
      high ← middle
    else
      return middle
    endif
  endwhile

※ 上の〔プログラム〕からの抜粋です(1字も変えていません)。

while が回り続けるかどうかを決めているのは low と high の2つだけ。ですから1周まわったあとに、この2つがどうなっているかを見れば決まります。ア・イ・ウ は条件から data と target が決まるので1回入れれば済みますが、エ だけは target が指定されていないので、こちらで選んで試します。

1周まわしたあとの low と high ── 終わるものから順に、最後が ウ

▲= middle が指す枡(配列の1つぶんの入れもの)/琥珀の箱= その周の middle/灰色の枡= 範囲から外れて、もう見ない枡/「通った枝」= その周に実行された行(上の〔プログラム〕からの抜粋。1字も変えていません)/赤い段= ここで不具合(無限ループ)が起きる

ア data = {5}、target = 5

1周目

15▲

low1

high1

middle1

通った枝

    else
      return middle

middle = (1 + 1) ÷ 2 の商 = 1。data[1] の 5 は target と等しいので else の枝へ。1周目に return 1 で終わります。

イ data = {5, 7}、target = 5(先頭の値)

1周目

15▲

27

low1

high2

middle1

通った枝

    else
      return middle

ア とちがうのは middle の計算だけ。(1 + 2) ÷ 2 は 1.5 なので商は 1 です。あとは ア と同じで、data[1] の 5 が target と等しく、1周目に return 1。

エ 要素に -1 が含まれている data = {-1, 0, 1}、target = -1

1周目

1-1

20▲

31

low1

high3

middle2

通った枝

    elseif (data[middle] > target)
      high ← middle

2周目

1-1▲

20

31

low1

high2

middle1

通った枝

    else
      return middle

エ だけ target を決めていないので、こちらで選びます。1周目の middle = 2。data[2] の 0 は target の -1 より大きいので high ← 2 ── 範囲が狭まりました。2周目の middle = 1 で、data[1] の -1 は target と等しいので return 1 で終わり。問われているのは「その場合は無限ループになる」ですから、終わる例が1つでも作れたら、条件として成り立ちません。

ウ data = {5, 7}、target = 7(末尾の値)

1周目

15▲

27

low1

high2

middle1

通った枝

    if (data[middle] < target)
      low ← middle

1周まわったあと

low1

high2

middle1

middle は イ と同じ 1。ちがうのは判定で、data[1] の 5 は target の 7 より小さいので、通るのは low ← middle、つまり low ← 1。low はもともと 1 なので何も変わらず、high はこの周で一度も触っていません。次の周も middle は 1、判定も同じ ── 止まりません。

1周まわって low と high がどちらも動かなかったのは、ウ だけ。

ア と イ は1周目、エ は2周目に return へたどり着きました。とくに エ は target をこちらで選べてしまうので、終わる例が1つ作れた時点で、「その場合は無限ループになる」の条件にはなりません。-1 という値は while の中で一度も特別扱いされていない ── 止まるかどうかを決めているのは low と high の動き方だけです。

答え合わせ

ウ 要素数が2 で,target がdata の末尾要素の値と等しい

ウ の data = {5, 7}、target = 7 を、最後まで押して確かめます。

1行ずつ追う search({5, 7}, 7) ── 要素数が2で、target が末尾の値

出典:科目B サンプル問題 問13(解答群 ウ の場合)


ループ開始前

配列

▲ いま読んでいる▲ いま書いた

いま計算していること

まだ計算していません

変数の状態

トレース表(進めると1行ずつ積み上がります)

止まらなくなる理由もひとことで。middle ← (low + high) ÷ 2 の商 は商が切り捨てなので、low と high が隣どうしになると、middle は前側、つまり low と同じ番号に落ちます。そこで low ← middle を実行しても何も変わらない ── これがこの関数の不具合です。範囲を半分ずつ狭めて探すこのやり方を2分探索といい、low ← middle + 1・high ← middle - 1 と書いてあれば、調べ終えた middle 番が必ず候補から外れるので、この止まり方は起きません。

次に読む

この問題でどこに手間取ったかで、行き先が変わります。

この記事で引用した資料

いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では問題文を改変せずに引用しています。

Copied title and URL