応用情報技術者 2012年 秋期 午前2 問07
問題文
次の関数の定義に従ってを再帰的に求めるとき、必要な加算の回数は幾らか。
選択肢
ア:3
イ:4(正解)
ウ:5
エ:7
🔒 解説は解答すると表示されます
再帰呼び出しの加算回数【午前2解説】
正解の理由
定義は「if x<2 then 1 else g(x-1)+g(x-2)」であり、ベースケースは (つまり のとき)です。したがって はベースケースではなく、 として加算が実行されます。
各「非ベース」の呼び出し(すなわち引数が2以上の呼び出し)は を計算する際に 1 回の加算を行います。 の再帰木を展開すると非ベース呼び出しは以下の4つになります:。したがって加算は合計で4回発生し、選択肢では イ に該当します。
各「非ベース」の呼び出し(すなわち引数が2以上の呼び出し)は を計算する際に 1 回の加算を行います。 の再帰木を展開すると非ベース呼び出しは以下の4つになります:。したがって加算は合計で4回発生し、選択肢では イ に該当します。
解法ステップ
- ベース条件を確認:ベースは → がベース(加算を行わない)。 が非ベース(加算を行う)。
- 再帰展開を行う:
- → ここで加算1回(g(4))
- → ここで加算1回(g(3))
- → ここで加算1回(g(2))
- 同様に は2箇所から呼ばれるため、もう1回の加算が発生(別の g(2))
- 非ベース呼び出しの個数を数えると になり、これが加算回数。
別のアプローチとして加算回数 を以下で定義できます:
これにより と計算できます。
選択肢別の誤答解説
- ア: 3
多くは をベース(加算が発生しない)と誤認して を1回ずつしか数えないため。だが は非ベースであり2回呼ばれるので誤り。 - イ: 正しい(加算4回)。上記の通り非ベース呼び出しが4回あるため。
- ウ: 5
1つ余分に数えてしまうケース。例えばベース呼び出し(g(1)やg(0))を加算回数に含めたり、同じ g(2) のカウント方法を誤って合算した結果などが原因。 - エ: 7
再帰木の全ノード数や完全二分木とみなして過剰に数えた誤り。実際には多くの葉がベースであり、加算は非ベース呼び出しのみで発生する。
よくある誤解
- 「g(2)はベース」だと勘違いする:ベース条件は なので は非ベースで必ず加算を行う点に注意。
- 同じ引数の関数呼び出しを1回しか数えてしまう:再帰的に同じ が複数回呼ばれる場合、それぞれで加算が発生する(メモ化しない場合)。
- 関数呼び出し回数と加算回数を混同する:呼び出し回数にはベース呼び出しが含まれるが、加算は非ベース呼び出しごとに1回だけ発生する。
補足コラム
この関数はフィボナッチ再帰に相当し、メモ化(動的計画法)を導入すると重複計算を避けられます。メモ化を用いると を一度だけ計算するため、加算回数は の再帰式で得られる通常の値より少なくなります。例えば をメモ化すると加算は の3回に減り、計算量は指数から線形 に改善されます。
簡単な比較用コード(説明目的):
# 単純再帰で加算回数をカウント
count = 0
def g(n):
global count
if n < 2:
return 1
count += 1 # g(n) が非ベースなので加算が行われる
return g(n-1) + g(n-2)
count = 0
g(4)
print(count) # 結果は 4
FAQ
Q. g(2) は本当に加算を行いますか?
A. はい。条件は「x<2」であり、2は含まれません。したがって で加算が1回行われます。
A. はい。条件は「x<2」であり、2は含まれません。したがって で加算が1回行われます。
Q. 加算回数と関数呼び出し回数は等しいですか?
A. いいえ。関数呼び出し回数はベース呼び出し()も含みますが、加算は非ベース呼び出しのみで行われます。加算回数は非ベース呼び出しの個数に等しいです。
A. いいえ。関数呼び出し回数はベース呼び出し()も含みますが、加算は非ベース呼び出しのみで行われます。加算回数は非ベース呼び出しの個数に等しいです。
Q. 一般の の加算回数はどう求めますか?
A. 先に示した漸化式を使います:。これを逐次計算すれば求まります。
A. 先に示した漸化式を使います:。これを逐次計算すれば求まります。
関連キーワード: 再帰、フィボナッチ、メモ化、漸化式、計算量、動的計画法

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

