基本情報技術者 2010年 秋期 午前(科目A) 問06
問題文
節点1, 2, …, nをもつ木を表現するために、大きさの整数型配列A[1], A[2], …, A[n]を用意して、節点iの親の番号をA[i]に格納する。節点kが根の場合はA[k]=0とする。表に示す配列が表す木の葉の数はいくつか。

選択肢
ア:1
イ:3
ウ:5(正解)
エ:7
🔒 解説は解答すると表示されます
親配列表現の葉数【午前解説】
正解の理由
与えられた親配列Aにおいて、葉とは「他の節点の親として一度も現れない節点」です。配列Aの値の集合(ただし0は根の印なので除く)に含まれる節点は少なくとも1つ以上の子を持つ節点、すなわち内部節点です。よって葉の個数は全節点数 から「親として出現する節点の種類数」を引いた数になります。今回、 であり配列の親として現れる節点の集合は (0は除く)で種類数は3です。したがって葉の個数は で、選択肢ウが正解です。
解法ステップ
- 親配列A[1..n] を確認する(ここではA = [0,1,1,3,3,5,5,5])。
- 配列の値のうち0を除いた異なる値(distinct values)を求める。これが「親として出現する節点の集合」である。
- 葉の個数は からその集合の要素数を引く:葉数 = 。
- 値を代入して計算する:。
数学的には、葉の個数を 、節点数を 、親として出現する節点の種類数を とすると
となります。
選択肢別の誤答解説
- ア: 1
1を選ぶのは根だけを葉と誤認する場合に起こります。根は子を持たなければ葉になりますが、今回の根(節点1)は子(節点2,3)を持っているため葉ではありません。 - イ: 3
「子が1つの節点」を数えるなどの別の誤りが考えられます。今回、子を持つ節点は1,3,5の3つですが、これは内部節点の数であって葉の数ではありません(葉は内部節点以外の節点)。 - エ: 7
7を選ぶのは「重複をカウントしない」「親として現れるかどうかではなく、子の総数を誤って数えた」などの計算ミスが原因です。親配列中に現れる値の重複(例えば5が3回現れる)は内部節点の種類数を増やすものではありません。重複は1つとして扱います。
よくある誤解
- 「親配列での登場回数を数えれば良い」と思い込み、異なる親ノードの種類ではなく出現回数の合計を用いるミス。重複は1回しか数えない(集合で見なす)点に注意してください。
- 0を親集合に含めてしまうミス。0は根の印なので葉判定のための親集合には含めません。
- 親として出現する節点の種類数の下限を常に1としてしまう誤解。一般には が成り立ちます(特に のときは少なくとも1つの親が存在するため )。
補足コラム
- 一般的なアルゴリズム実装はO(n) で行えます。親配列を1回走査して0を除く親番号を集合に入れ、その集合のサイズを用いて葉数を求めます。
- 親配列は根を指す要素に0を使う慣習がありますが、別の表現(-1やself-indexing)を使う問題もあり得ます。符号や特別値に注意して同様の集合処理を行ってください。
例(Python、1-basedを想定した簡単な実装):
A = [0,1,1,3,3,5,5,5] # 長さn (=8)
parents = set(x for x in A if x != 0)
n = len(A)
leaves = n - len(parents)
print(leaves) # 5
FAQ
Q: 配列内に親番号が自分自身の値として書かれているときは?
A: 木の定義では自己ループは許されません。自己番号が親として現れる場合は、その節点が子を持つ(内部節点)と扱いますが、与えられた構造が「木」であることを前提に問題が作られているはずです。
A: 木の定義では自己ループは許されません。自己番号が親として現れる場合は、その節点が子を持つ(内部節点)と扱いますが、与えられた構造が「木」であることを前提に問題が作られているはずです。
Q: 複数の根(森)の場合はどうする?
A: 設問が「木」を対象としている限り根は1つですが、一般に森林(複数根)でも同様の考え方が使えます。各根はA[i]=0となり、葉の個数は同様に で求まります。
A: 設問が「木」を対象としている限り根は1つですが、一般に森林(複数根)でも同様の考え方が使えます。各根はA[i]=0となり、葉の個数は同様に で求まります。
関連キーワード: 親配列、葉の計算、木構造、集合操作、アルゴリズム設計

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

