無限ループ= 止まらずに回り続けること。それが起きる 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(解答群 ウ の場合)
ループ開始前
配列
いま計算していること
変数の状態
return で返した値
トレース表(進めると1行ずつ積み上がります)
止まらなくなる理由もひとことで。middle ← (low + high) ÷ 2 の商 は商が切り捨てなので、low と high が隣どうしになると、middle は前側、つまり low と同じ番号に落ちます。そこで low ← middle を実行しても何も変わらない ── これがこの関数の不具合です。範囲を半分ずつ狭めて探すこのやり方を2分探索といい、low ← middle + 1・high ← middle - 1 と書いてあれば、調べ終えた middle 番が必ず候補から外れるので、この止まり方は起きません。
次に読む
この問題でどこに手間取ったかで、行き先が変わります。
while ── 「条件が偽になるまで回す」形がつかめなかった人へ問12サンプル問題 問12 ── 2つの配列がどれだけ似ているかを返す回です一覧科目B 全44問の解説 ── 続けて解きたい人へこの記事で引用した資料
いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では問題文を改変せずに引用しています。

