再帰(末尾再帰・メモ化)とは?再帰は関数が自分自身を呼び出す手法

公開: 更新: カテゴリ: テクノロジ系

30秒で結論

再帰とは(全体像)

再帰は、関数の中で自分自身をもう一度呼ぶ書き方。「大きな問題」を「ひとまわり小さい同じ問題」に置きかえていき、最後にいちばん小さいところで答えを確定する。

そのために2つの要素が必要だ。

いちばん大事なのは、基底条件がないと止まらないこと。終わりの条件がなければ自分を呼び続け、メモリを使い切ってスタックオーバーフロー(あふれ)で止まってしまう。だから基底条件は必須だ。


詳しく:基底条件・末尾再帰・メモ化だけ覚えれば戦える

ここが記事の心臓部。まずは再帰の2要素

再帰の必須要素

要素役割
基底条件これ以上分けない最小ケース(止まる条件)
再帰呼び出しより小さな問題で自分自身を呼ぶ

たとえば階乗(1からnまでの掛け算)は、「n×(n−1の階乗)」と自分を呼び、最後に「0の階乗=1」という基底条件で止まる。基底条件を書き忘れると止まらないので、ここが最大の注意点だ。

次に、よく問われる末尾再帰メモ化

末尾再帰とメモ化

用語内容
末尾再帰自分の呼び出しが処理の「最後」にある形。ループに最適化できる
メモ化計算した結果を保存し、同じ計算を再利用する

末尾再帰は、再帰呼び出しが処理のいちばん最後にある形。これは一部の言語でループに置きかえて最適化でき、メモリを節約できる(だから「再帰は反復より必ず遅い」とは限らない)。

メモ化は、一度計算した答えを覚えておいて使い回すこと。たとえばフィボナッチ数列を素朴に再帰で計算すると、同じ計算を何度も繰り返してO(2^n)と爆発的に遅くなる。メモ化すればO(n)まで速くなる。つまり、一度出した答えをメモして再計算を省くのがメモ化のねらい、というわけだね。

わかりやすく言い換えると

要するに、再帰は「マトリョーシカ人形」だ。

再帰呼び出し … 人形を開けると、中にひとまわり小さい同じ人形が入っている

基底条件 … いちばん小さい人形(もう開かない)。ここで止まる

基底条件を書き忘れるのは「いつまでも人形が出てくる」状態で、止まらずにあふれてしまう(スタックオーバーフロー)。

メモ化は「一度出した答えをメモ帳に控えておく」こと。同じ問いが来たら、計算し直さずメモを見るだけ。だからフィボナッチのようなむだな繰り返しが消えて速くなる、というわけだね。


試験のツボ

🔴 一番出る:基底条件が必須

①基底条件=これ以上分けない最小ケース(止まる条件)

②書き忘れると止まらず、スタックオーバーフローになる

🔴 次に出る:末尾再帰とメモ化

①末尾再帰=呼び出しが処理の最後にある形。ループに最適化できる

②メモ化=計算結果を使い回す(フィボナッチがO(2^n)→O(n))

🟡 押さえると安定:再帰の速さ

①「再帰は反復より必ず遅い」とは限らない

②末尾再帰の最適化やメモ化で速くできる


よくある間違い

「再帰には基底条件がなくても問題なく動く」→ ✗  基底条件がないと止まらず、スタックオーバーフローになる。必須。

「再帰は反復(ループ)より必ず遅い」→ ✗  末尾再帰はループに最適化でき、同等の速さになりうる。

「メモ化をしてもフィボナッチの計算量は変わらない」→ ✗  素朴な再帰のO(2^n)が、メモ化でO(n)まで速くなる。


試験での出題パターン

実際の問題でたしかめてみよう。

オリジナル問題1(基底条件)

📝 オリジナル問題 1 基底条件の必要性

再帰の基底条件に関する次の記述のうち、正しいものはどれか。

  1. 基底条件は処理を速くするための工夫であり、なくても再帰は正しく止まる
  2. 基底条件は計算結果を保存するしくみで、書かなくても問題は起きない
  3. 基底条件は止まる条件で、ないと止まらずスタックオーバーフローになる
  4. 基底条件は再帰には不要で、ループにだけ必要となる条件のことである
オーエスペン
オーエスペン 解答・解説

解答は 3 だよ。

基底条件はこれ以上分けない最小ケース(止まる条件)で、これがないと再帰が止まらずスタックオーバーフローになるんだ。だから必須だよ。

選択肢1は「なくても止まる」が誤り。選択肢2は「計算結果を保存」でメモ化と取り違え。選択肢4は「再帰に不要」が誤りだよ。

選択肢判定理由
1なければ止まらない
2それはメモ化の説明
3止まる条件・ないとSOFになる
4再帰に必須

オリジナル問題2(メモ化)

📝 オリジナル問題 2 メモ化の効果

メモ化に関する次の記述のうち、正しいものはどれか。

  1. 計算結果を保存して使い回し、フィボナッチをO(2^n)からO(n)に速める
  2. 計算結果を毎回すべて捨てるしくみで、計算量はかえって増えるものである
  3. メモ化は再帰を必ず無限ループにする、避けるべきとても危険な手法のことである
  4. メモ化をしてもフィボナッチの計算量は変わらず、O(2^n)のままである
オーエスペン
オーエスペン 解答・解説

解答は 1 だよ。

メモ化は計算結果を保存して使い回すことで、むだな再計算を消すんだ。素朴な再帰だとO(2^n)で爆発するフィボナッチが、メモ化でO(n)まで速くなるよ。

選択肢2は「毎回捨てる・増える」が誤り。選択肢3は「無限ループにする危険」が誤り。選択肢4は「変わらない」が誤りだよ。

選択肢判定理由
1結果を使い回しO(2^n)→O(n)
2捨てずに保存して使い回す
3無限ループにはしない
4メモ化で速くなる

オリジナル問題3(末尾再帰)

📝 オリジナル問題 3 末尾再帰

末尾再帰に関する次の記述のうち、正しいものはどれか。

  1. 末尾再帰は基底条件を不要にするしくみで、止まる条件を書かなくてよい
  2. 末尾再帰は呼び出しが処理の最後にある形で、ループへと最適化できる
  3. 末尾再帰は必ず反復(ループ)より遅くなる、避けるべき書き方である
  4. 末尾再帰は計算結果を保存するしくみで、メモ化とまったく同じものだ
オーエスペン
オーエスペン 解答・解説

解答は 2 だよ。

末尾再帰は自分の呼び出しが処理の最後にある形で、一部の言語ではループに最適化できるんだ。だからメモリを節約でき、「再帰は必ず遅い」とは限らないよ。

選択肢1は「基底条件を不要にする」が誤り(基底条件は必要)。選択肢3は「必ず遅い」が誤り。選択肢4は「メモ化と同じ」が誤りだよ。

選択肢判定理由
1基底条件は必要
2呼び出しが最後・ループに最適化できる
3最適化で同等になりうる
4メモ化とは別もの

まとめ

押さえどころ

次に学ぶ


執筆: SikakuQuest編集部

勉強は、クエストになった。

資格の勉強を、冒険に変えるRPG学習アプリ

App Storeで見る