AI EducademyAIEducademy
🌳

AI基礎

🌱
AI Seeds(種)

ゼロから始める

🌿
AI Sprouts(芽)

基礎を築く

🌳
AI Branches(枝)

実践に活かす

🏕️
AI Canopy(樹冠)

深く学ぶ

🌲
AI Forest(森)

AIをマスターする

🔨

AIマスタリー

✏️
AI Sketch(スケッチ)

ゼロから始める

🪨
AI Chisel(鑿)

基礎を築く

⚒️
AI Craft(制作)

実践に活かす

💎
AI Polish(磨き上げ)

深く学ぶ

🏆
AI Masterpiece(傑作)

AIをマスターする

🚀

キャリア準備

🚀
面接ローンチパッド

旅を始めよう

🌟
行動面接マスター

ソフトスキルをマスター

💻
技術面接

コーディング面接を突破

🤖
AI・ML面接

ML面接をマスター

🏆
オファーとその先

最高のオファーを獲得

全プログラムを見る→

ラボ

7つの実験がロード済み
🧠ニューラルネットワーク プレイグラウンド🤖AIか人間か?💬プロンプトラボ🎨画像生成😊感情分析ツール💡チャットボットビルダー⚖️倫理シミュレーター
🎯模擬面接ラボへ入る→
nav.journeyブログ
🎯
概要

すべての人にAI教育をアクセス可能にする

❓
nav.faq

Common questions answered

✉️
Contact

Get in touch with us

⭐
オープンソース

GitHubで公開開発

始める
AI EducademyAIEducademy

MITライセンス。オープンソース

学ぶ

  • アカデミックス
  • レッスン
  • ラボ

コミュニティ

  • GitHub
  • 貢献する
  • 行動規範
  • 概要
  • よくある質問

サポート

  • コーヒーをおごる ☕
  • footer.terms
  • footer.privacy
  • footer.contact
AI & エンジニアリング アカデミックス›✏️ AI Sketch(スケッチ)›レッスン›再帰とバックトラッキング
🧩
AI Sketch(スケッチ) • 中級⏱️ 20 分で読める

再帰とバックトラッキング

Recursion Fundamentals

A recursive function calls itself with a smaller version of the problem until it hits a base case that stops the chain.

Every recursion needs two things:

  1. Base case - the simplest input where you return directly.
  2. Recursive case - break the problem down and call yourself.
def factorial(n):
    if n <= 1:        # base case
        return 1
    return n * factorial(n - 1)  # recursive case

The Call Stack - Visualised

Each recursive call pushes a frame onto the call stack. When the base case returns, frames pop in reverse order.

factorial(4)
  → factorial(3)
    → factorial(2)
      → factorial(1) → returns 1
    ← returns 2
  ← returns 6
← returns 24

If there's no base case, the stack overflows. Python's default recursion limit is 1,000 frames.

🤯
Python's default recursion limit of 1,000 is intentionally conservative. You can raise it with sys.setrecursionlimit(), but iterative solutions are usually preferred for deep recursion.

Fibonacci - The Classic Trap

The naïve recursive Fibonacci is O(2ⁿ) because it recomputes the same sub-problems. Memoisation fixes this in O(n) time and space.

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)
Recursion tree for Fibonacci showing repeated sub-problems
Without memoisation, fib(5) makes 15 calls. With it, only 5.

Backtracking - Try Everything, Then Undo

Backtracking is recursion with a twist: you make a choice, recurse, then undo the choice before trying the next option. Think of it as exploring a maze - walk forward, hit a dead end, walk back, try the next path.

The Backtracking Template

def backtrack(state, choices):
    if is_solution(state):
        result.append(state.copy())
        return
    for choice in choices:
        if is_valid(choice):
            state.add(choice)       # choose
            backtrack(state, ...)   # explore
            state.remove(choice)    # un-choose

This three-step pattern - choose, explore, un-choose - is the backbone of nearly every backtracking problem.

🧠クイックチェック

In the backtracking template, why do we undo the choice after the recursive call?

レッスン 8 / 100%完了
←二分探索パターン

Discussion

Sign in to join the discussion

lessons.suggestEdit

Permutations

Generate all orderings of [1, 2, 3]. At each level, pick an unused number, recurse, then un-pick.

         []
      /   |   \
    [1]  [2]  [3]
    / \   ...
 [1,2] [1,3]
   |      |
[1,2,3] [1,3,2]  ... (6 total)

There are n! permutations, so the time complexity is O(n × n!).

Combinations and Subsets

Combinations (n choose k): at each element, include it or skip it, but only recurse forward to avoid duplicates.

Subsets: same idea without a size constraint - every node in the recursion tree is a valid subset. There are 2ⁿ subsets.

🤔
Think about it:Permutations produce n! results while subsets produce 2ⁿ. For n=10, that's 3,628,800 vs 1,024 - a massive difference. Why?

N-Queens - Walkthrough

Place N queens on an N×N board so none attack each other. For N=4:

. Q . .
. . . Q
Q . . .
. . Q .

Strategy: place one queen per row. For each row, try every column. Check column, main diagonal, and anti-diagonal conflicts. If safe, place and recurse to the next row. If stuck, backtrack.

Track conflicts with three sets: cols, diag (row − col), and anti_diag (row + col).

🧠クイックチェック

In the N-Queens problem, how do we efficiently check diagonal conflicts?

Sudoku Solver - Concept

Find an empty cell, try digits 1–9. For each digit, check row, column, and 3×3 box constraints. If valid, place and recurse. If no digit works, undo and backtrack. The pruning from constraints makes it tractable despite the huge search space.

Word Search in a Grid

Given a 2D board of letters and a target word, start from every cell and DFS in four directions, matching one character at a time. Mark cells as visited during recursion and unmark on backtrack to allow other paths.

Time Complexity of Backtracking

The cost depends on the branching factor (choices per step) and depth (steps to a solution). For b branches and d depth: O(bᵈ).

| Problem | Branching | Depth | Complexity | |---------|-----------|-------|------------| | Permutations | n, n−1, … | n | O(n!) | | Subsets | 2 | n | O(2ⁿ) | | N-Queens | ~n | n | O(n!) worst case |

Pruning to Optimise

Pruning means skipping branches you know will fail. Examples:

  • N-Queens: skip columns already occupied.
  • Sudoku: skip digits that violate constraints.
  • Combination sum: skip if remaining sum < 0.

Good pruning can turn an impractical search into a fast one.

🧠クイックチェック

What does pruning do in a backtracking algorithm?

🤔
Think about it:Many backtracking problems can also be solved with dynamic programming. What is the key difference in approach between the two?

📚 Further Reading

  • NeetCode - Backtracking playlist - curated problems with video walkthroughs
  • Tech Interview Handbook - Recursion - patterns and common pitfalls
  • LeetCode Backtracking study plan - progressive problem set