基本情報技術者 2012年 秋期 午前(科目A) 問05
問題文
四つのデータA, B, C, Dがこの順に入っているキューと空のスタックがある。手続pop_enq, deq_pushを使ってキューの中のデータをD, C, B, Aの順に並べ替えるとき、deq_pushの実行回数は最小で何回か。ここで、pop_enqはスタックから取り出したデータをキューに入れる操作であり、deq_pushはキューから取り出したデータをスタックに入れる操作である。
選択肢
ア:2
イ:3(正解)
ウ:4
エ:5
四つのデータを逆順に並べ替えるときの deq_push 回数【午前2 解説】
要点まとめ
- 結論:deq_pushは最小で3回。先頭から3個をスタックに移し,残ったDを先頭にしてからスタックを順にキューへ戻せばD,C,B,Aになります。
- 根拠:スタックはLIFOなので,先にスタックへ入れた要素ほど後にキューに戻り,これを利用して順序を逆にできます。
- 差がつくポイント:全要素を一度にスタックに移す必要はないと認識し,最後の要素をキューに残す発想でdeq_push回数を減らせます。
正解の理由
正解: イ(3回)
手続deq_pushは「キューからスタックへ移す」、pop_enqは「スタックからキューへ戻す」操作です。初期キュー[A, B, C, D](先頭A)に対し,先頭から3回 deq_push で A,B,C をスタックに入れるとキューには D だけが残ります。スタックは上から C,B,A の順になっているため,pop_enq を3回行えばキューの末尾に C,B,A が順に付加され,結果としてキューは [D, C, B, A] となります。これを達成するための deq_push の最少回数は3回であり,それより少ない回数では D を先頭に残しつつ残りを逆順で付加することができません。
手続deq_pushは「キューからスタックへ移す」、pop_enqは「スタックからキューへ戻す」操作です。初期キュー[A, B, C, D](先頭A)に対し,先頭から3回 deq_push で A,B,C をスタックに入れるとキューには D だけが残ります。スタックは上から C,B,A の順になっているため,pop_enq を3回行えばキューの末尾に C,B,A が順に付加され,結果としてキューは [D, C, B, A] となります。これを達成するための deq_push の最少回数は3回であり,それより少ない回数では D を先頭に残しつつ残りを逆順で付加することができません。
よくある誤解
- 「全要素を一度スタックへ移さないと逆順にならない」:最後の要素をキューに残せば良く,すべて移す必要はありません。
- 「pop_enq の回数も同じだけ数えるべき」:問題は deq_push の最小回数を問うており,pop_enq は数える対象外ですが,実際には deq_push = 3 に対して pop_enq = 3 で済みます。
- 「キューの前後の向きを取り違える」:問題文の「この順に入っている」は先頭が A, 末尾が D と理解する点を誤ると解答を間違えます。
解法ステップ
- 初期状態:キュー Q = [A, B, C, D](先頭左),スタック S = [](上が左側表記)。
- deq_push を3回実行:
- deq_push(A) → S = [A], Q = [B, C, D]
- deq_push(B) → S = [B, A], Q = [C, D]
- deq_push(C) → S = [C, B, A], Q = [D]
- pop_enq を3回実行(スタックの上から順にキューの末尾へ):
- pop_enq() → S = [B, A], Q = [D, C]
- pop_enq() → S = [A], Q = [D, C, B]
- pop_enq() → S = [], Q = [D, C, B, A]
- 結果:Q = [D, C, B, A]。deq_push の実行回数は3回で最小。
選択肢別の誤答解説
- ア: 2
2回では先頭から2個(A,B)をスタックへ移せますが,残りのCとDを逆順で並べ替えるためにはさらにdeq_pushが必要であり,最終的にDを先頭にして完全に逆順にできません。 - イ: 3(正解)
先頭から3個をスタックへ移し,残ったDを先頭にしてからスタックを順に戻すことでD,C,B,Aを実現します。 - ウ: 4
4回は可能な手順(すべてスタックへ移してから戻す)ですが,最小回数ではありません。問題は最小回数を問うため不正解。 - エ: 5
5回は不要かつ無駄な操作回数です。最小値より大きいので誤りです。
補足コラム
- 一般化:要素数を とすると,キューの順序を完全に逆転させる最小の deq_push 回数は です。最後の要素をキューに残し,残り 個をスタックに移してから順に戻せば良いためです。
- 操作計画のコツ:逆順にしたい要素のうち「最後に来るべきもの」をキューに残す発想を持つと,スタックのLIFO性を最短で活かせます。
FAQ
Q1. pop_enq の回数も最小化すべきですか?
A1. 本問は deq_push の最小回数を問うていますが,この手順では pop_enq も3回で済みます。問題によっては両方を最小化する設問もあり得ます。
A1. 本問は deq_push の最小回数を問うていますが,この手順では pop_enq も3回で済みます。問題によっては両方を最小化する設問もあり得ます。
Q2. スタックを使わずに可能ですか?
A2. スタックを使わないと,通常のキュー操作だけでは順序を逆にできません(循環や一時記憶が必要)。ここではスタックとキューの組合せが必須です。
A2. スタックを使わないと,通常のキュー操作だけでは順序を逆にできません(循環や一時記憶が必要)。ここではスタックとキューの組合せが必須です。
Q3. スタックの初期状態が空でない場合はどうなる?
A3. スタックに既存要素があると操作順や最少回数が変わります。本問は空スタックを前提としているため,その条件が重要です。
A3. スタックに既存要素があると操作順や最少回数が変わります。本問は空スタックを前提としているため,その条件が重要です。
関連キーワード: キュー, スタック, LIFO, FIFO, 操作列, アルゴリズム, データ構造, 手続き最小化

\ せっかくなら /
基本情報技術者を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

