基本情報技術者 2010年 秋期 午前(科目A) 問05
問題文
A, B, C, Dの順に到着するデータに対して、一つのスタックだけを用いて出力可能なデータ列はどれか。
選択肢
ア:A, D, B, C
イ:B, D, A, C
ウ:C, B, D, A(正解)
エ:D, C, A, B
##: スタックで出力可能なデータ列はどれか【午前2 解説】
要点まとめ
- 結論:入力順序 A,B,C,D に対して、単一のスタックのみを用いて出力可能なのは選択肢ウの C,B,D,A のみで、他はスタックの LIFO 性により実現できません。
- 根拠:スタックは後入れ先出し(LIFO)で、ある要素より後にプッシュされた要素が上にある間はその下の要素を取り出せないという入出力制約が成否を決定します。
- 差がつくポイント:出力順を左から見て必要なら入力を順にプッシュし、トップが一致したらポップする貪欲シミュレーションで可否を短時間で判定できます。
正解の理由
正解: ウ
出力 C,B,D,A は次の操作で実現できます(入力は左から A → B → C → D の到着順)。
出力 C,B,D,A は次の操作で実現できます(入力は左から A → B → C → D の到着順)。
- push A(スタック上: [A])
- push B([A, B])
- push C([A, B, C])
- pop → C を出力(出力列: C、スタックは [A, B])
- pop → B を出力(出力列: C, B、スタックは [A])
- push D([A, D])
- pop → D を出力(出力列: C, B, D、スタックは [A])
- pop → A を出力(出力列: C, B, D, A、スタックは空)
上記のプッシュ/ポップ操作はスタックの LIFO 規則に従っており、階層関係を破ることなく目的の順序を作れます。
よくある誤解
- 「すべての順列がスタック一つで作れる」と思い込む:実際は LIFO 制約により多数の順列が不可能で、特定の逆転(上にある要素が先に出る必要がある場合)が問題になります。
- 「一度全てプッシュしてからポップすればどの順番でもできる」との誤認:全てプッシュしてからポップすると逆順(D,C,B,A)になるだけで、任意順にはなりません。
- 「部分的に別解があるはず」と考えて操作を雑に推測すること:可否判定は貪欲にシミュレーションするか、逆転関係を論理的に検討するのが確実です。
解法ステップ
- 目標出力列を左から順に見ます(ここでは C→B→D→A)。
- 入力列の先頭から順に、必要な要素がスタックのトップに来るまで push を繰り返します。
- 目標の要素がスタックのトップに来たら pop して出力に追加します。
- 目標要素を出力できない(入力を全て使ってもトップに来ない)場合は不可能と判断します。
- これを全要素に対して行い、最後まで成功すれば可、途中で失敗すれば不可です。
(この手順は O(n) の貪欲シミュレーションで実装できます。)
選択肢別の誤答解説
- ア: A, D, B, C
A を最初に出すのは可能(push A → pop A)。しかし次に D を出すには B と C をスタックに積む必要があり、D を pop した後に B を先に出すことはできません(C が B の上にあるため)。よって不可。 - イ: B, D, A, C
B を最初に出す操作は可能(push A, push B, pop B)。その後 D を出すには C と D を積むが、D を出した後に A を出すとなると C が A の上に残っており A を先に出せないため不可。 - ウ: C, B, D, A
前節の通り、操作列(push A, push B, push C, pop C, pop B, push D, pop D, pop A)で実現可能。よって正解。 - エ: D, C, A, B
D を最初に出すには全てプッシュしてから D を pop するが、その後 C を出しても残るスタックは [A,B](B が A の上)であり、A を C の後に出すことが要求されても B が邪魔をして A を先に取り出せないため不可。
補足コラム
- 単一スタックで入力順を出力順に変換可能な並びの総数は n 個の場合カタラン数(Catalan number)で表されます(例えば n=4 のときは 14 通り)。
- 実務的には、スタックで実現できるかは「ある要素を出したい時、それより前に入った要素のうち出力済でないものが上に出てきてしまうか」をチェックするだけで判定できます。
- 複数スタックやキュー+スタック等を組み合わせると可能な並びのクラスは変わります。問題によって許される操作の違いに注意しましょう。
FAQ
Q1: 素早く判定するコツは?
A1: 出力列を左から見て、必要なら入力を順に push してトップが目的要素になるまで待ち、トップが目的要素なら pop する貪欲法を使うと素早く判定できます。
A1: 出力列を左から見て、必要なら入力を順に push してトップが目的要素になるまで待ち、トップが目的要素なら pop する貪欲法を使うと素早く判定できます。
Q2: 全て push してから pop する戦略は有効か?
A2: それはただの逆順(入力の完全逆)しか作れないため、多くの順列は作れません。状況に応じて途中で pop する必要があります。
A2: それはただの逆順(入力の完全逆)しか作れないため、多くの順列は作れません。状況に応じて途中で pop する必要があります。
Q3: この考え方はどんな問題で使える?
A3: スタックの操作問題、カタラン数に関する組合せ問題、入出力順序の可否判定など幅広く使えます。
A3: スタックの操作問題、カタラン数に関する組合せ問題、入出力順序の可否判定など幅広く使えます。
関連キーワード: スタック, LIFO, プッシュ ポップ, データ構造, スタック順列, カタラン数, 貪欲アルゴリズム, 試験対策

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

