並んだ点数から、いちばん大きいものを選ぶプログラムです。{80, 65, 90, 72} でいちばん大きいのは 90。人は一目で分かりますが、プログラムは一度に1つしか見られません。その縛りの中で、どう見つけるかを追います。
第2部 定番処理の型 全27回
A1-1トレース表の書き方A1-2繰返しのトレースA1-3配列のトレースA2-1配列を全部見るA2-2最大・最小を見つけるA2-3探す(線形探索)A2-4入れる・消すA2-52つの配列を突き合わせるA3-12次元配列の走査A3-22次元配列の集計A4-1文字列を1文字ずつA4-2文字列照合A5-1交換して並べるA5-2挿入ソートA6分割して並べるA7-12分探索A7-2ハッシュ表探索A8-1再帰とはA8-2再帰のトレースA9スタックとキューA10-1リストを読むA10-2リストの挿入と削除A11木構造A12木の巡回A13グラフA14AI・データを題材にしたプログラムA15ファイル処理
まず、通しで見る
2分ほどの動画です(音声つき)。前半で、プログラムを上から1行ずつ読みます。最大を見つける形は、どの問題でも同じだと分かります。後半は、この形でいちばん間違えやすい「最初に何を入れて始めるか」。選び方を1つ誤ると、配列のどこにも無い値が答えとして出てきます。その壊れ方まで見ておきます。
最大を見つける(1分55秒・音声つき)
再生できないときは、この下の図と説明で同じ内容を追えます。
ここから、動画と同じ順で、文章でも追います。
プログラムを、上から読む
追いかけるのは、4人の点数からいちばん大きいものを選ぶ、このプログラムです。
整数型の配列: ten ← {80, 65, 90, 72}
整数型: saidai ← ten[1]
整数型: i
for (i を 2 から tenの要素数 まで 1 ずつ増やす)
if (ten[i] > saidai)
saidai ← ten[i]
endif
endfor
saidaiの値 を出力する
出力は 90 です。4人の点数のうち、いちばん大きい値です。上から順に読みます。
上から読む
-
整数型の配列: ten ← {80, 65, 90, 72}いちばん上の行。点数が4つ、配列tenに入っています。 -
整数型: saidai ← ten[1]
つぎの行。最大を入れておく箱saidaiに、配列の1番目の値を入れます。これが暫定の最大です。まだ1つしか見ていないので、いまのところ 80 が最大、という意味です。 -
整数型: i for (i を 2 から tenの要素数 まで 1 ずつ増やす)
くり返しの行。番号を入れておく箱iを用意して、くり返しに入ります。iは 2 から始まります。1番目は、もう暫定の最大に入れてあるので、2番目からです。tenの要素数は配列に入っている値の個数(ここでは 4)なので、iは 2、3、4 と進みます。 -
if (ten[i] > saidai) saidai ← ten[i] endifその中の条件分岐。もし、いま見ている値ten[i]のほうが、暫定の最大より大きければ、つぎの行でsaidaiを入れ替えます。大きくなければ、何もしません。endifまでが、この条件分岐のひとかたまりです。 -
endfor saidaiの値 を出力する
最後まで回すと、いちばん大きい 90 がsaidaiに残り、それを出力します。endforで1周がおわり、iが 4 を超えたところでくり返しも終わります。
比べる相手は、いつも1つだけ
プログラムは一度に1つしか見られません。だから「暫定の最大」を1つ持っておき、いま見ている値とだけ比べる。全部見終わったとき、手元に残っているのが最大です。
1周ずつ、ゆっくり見る
ここからは、くり返しを1周ずつ追います。1周ごとに、トレース表に1行書きます。列は「周」「i」「ten[i]」「saidai」の4つです。
はじめに。配列の1番目の 80 を、暫定の最大 saidai としておきます。まだくり返しには入っていないので、表の1行目は「はじめ」です。
ループの1周目。番号は 2 から始まるので、配列の2番目、65 から見ます。条件分岐で、65 と、暫定の 80 をくらべます。大きくないので、入れ替えません。saidai は 80 のままです。
ループの2周目。配列の3番目の 90 です。90 は、暫定の 80 より大きい。暫定の最大を 90 に入れ替えます。
2周目:90 と 80 をくらべて、入れ替える
整数型の配列: ten ← {80, 65, 90, 72}
いま見ている値と、暫定の最大
180
265
390▲
472
くらべる相手は、暫定の最大 saidai(いまは 80)だけ
if (ten[i] > saidai) 90 > 80 は成り立つ
| 周 | i | ten[i] | saidai |
|---|---|---|---|
| はじめ | ー | 80 | 80 |
| 1周 | 2 | 65 | 80 |
| 2周 | 3 | 90 | 90 |
成り立ったので、つぎの行へ進む
saidai ← ten[i] 暫定の最大を書き換える
180
265
390
472
前の saidai80
いまの saidai90
80 → 90。入れ替わったのは、3周のうちこの1回だけ
くらべて、大きければ入れ替える。それだけを最後までくり返す
ループの3周目。配列の4番目の 72。暫定の 90 より大きくないので、そのままです。
できあがったトレース表がこれです。入れ替わったのは、3周のうち1回だけでした。
| 周 | i |
ten[i] |
saidai |
|---|---|---|---|
| はじめ | — | 80 | 80 |
| 1周 | 2 | 65 | 80 |
| 2周 | 3 | 90 | 90 |
| 3周 | 4 | 72 | 90 |
自分でトレース表を書くときも、入れ替えが起きなかった周は、前の行と同じ値をもう一度書くだけです。同じ値が続くマスを空けておく書き方は A1-3 にあります。
同じ内容を、自分の手で1行ずつ進めてみてください。
「最大を見つける」を1行ずつ動かす
当サイトオリジナルの例題
ループ開始前
配列
いま計算していること
変数の状態
出力
トレース表(進めると1行ずつ積み上がります)
最大の値ではなく位置を答える問題があります。そのときは、入れ替える行の隣に ichi ← i も書きます。入れ替えが起きた周の i(この例では 3)が、そのまま位置になります。
最初の1つに、何を入れるか
はじめに、どの値を入れておくか。ここで、いちばん多くの人がつまずきます。
もし、saidai ← 0 と、0 から始めるとどうなるでしょうか。気温のように、ぜんぶが負の数のときは、0 より大きい値が1つもありません。
整数型の配列: kion ← {-5, -3, -9}
整数型: saidai ← 0
整数型: i
for (i を 1 から kionの要素数 まで 1 ずつ増やす)
if (kion[i] > saidai)
saidai ← kion[i]
endif
endfor
saidaiの値 を出力する
出力は 0 です。条件分岐が一度も成り立たないので、saidai は最初に入れた 0 のまま最後まで動きません。答えが 0 になり、配列のどこにも無い値が出てきます。
0 から始めると、全部が負の数のとき壊れる
整数型の配列: kion ← {-5, -3, -9}
誤り ── saidai ← 0 から始める
1-5
2-3
3-9
0 より大きい値が1つも無いので、条件分岐が一度も成り立たない
その結果
出力0
配列のどこにも無い 0 が、答えとして出てくる
正しい ── saidai ← kion[1] から始める
1-5▲
2-3
3-9
1番目の -5 を入れ、2番目からくらべる。-5 と -3 では -3 のほうが大きい
その結果
出力-3
必ず配列の中の値が答えになる
迷ったら「1番目を入れて、2番目から比べる」
1番目を入れて、2番目からくらべる。これなら壊れません。1番目は必ず配列の中にある値なので、どんな値が並んでいても、答えが配列の外の値になることはありません。点数のように「値は 0 以上」と問題文に書いてあれば 0 でも動きますが、その保証が無いときは迷わず1番目です。
最小は、不等号を逆にするだけ
いちばん小さい値を探すときも、まったく同じ形です。変わるのは条件分岐の不等号の向きだけ。「いま見ている値のほうが小さければ、入れ替える」にします。
整数型の配列: ten ← {80, 65, 90, 72}
整数型: saisho ← ten[1]
整数型: i
for (i を 2 から tenの要素数 まで 1 ずつ増やす)
if (ten[i] < saisho)
saisho ← ten[i]
endif
endfor
saishoの値 を出力する
出力は 65 です。1周目で 65 < 80 が成り立って saisho が 65 になり、そのあとの 90 と 72 は 65 より小さくないので、そのままです。
変えるのは1か所
最大if (ten[i] > saidai) 大きければ入れ替える
最小if (ten[i] < saisho) 小さければ入れ替える
試験では、この不等号の向きが空欄になることがよくあります。「大きいほうを残したいのか、小さいほうを残したいのか」を、問題文の日本語で確かめてから埋めてください。
次に読む
| A2-3 | 配列から探す ─ 線形探索と「見つからなかったとき」 |
| A2-1 | 配列を全部見る ─ ten[i] と for の読み方 |
| G5 | 選択処理 if ─ 枝がどう選ばれるか |
| 目次 | 基本情報技術者試験 科目B 攻略ガイド |
この記事で引用した資料
いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では問題文を改変せずに引用しています。
本文の例題は当サイトのオリジナルです。
