Keito

© 2024 Keito

技術ブログとポートフォリオ

フィボナッチ数列(動的計画法)

動的計画法で効率的に計算し、再帰版の問題を解決しよう

O(n)
時間計算量(線形)
O(n)
空間計算量
初級
難易度
DP
手法

🔧 実行設定

計算対象:
F(10)
メモリ使用量:
11 要素
✅ 大きな値でも効率的に計算可能

📚 推奨値

🔢 フィボナッチ数列

F(0)=0, F(1)=1, F(2)=1, F(3)=2, F(4)=3, F(5)=5, F(6)=8, F(7)=13, F(8)=21, F(9)=34, ...
🚀

アルゴリズムを実行してください

左側の設定パネルからnの値を設定し、「DP計算実行」ボタンを押してください

💻 実装例(JavaScript)

function fibonacciDP(n) {
    // エッジケース
    if (n <= 1) {
        return n;
    }
    
    // DPテーブルを初期化
    const dp = new Array(n + 1);
    dp[0] = 0;  // F(0) = 0
    dp[1] = 1;  // F(1) = 1
    
    // ボトムアップで計算
    for (let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    
    return dp[n];
}

// メモリ最適化版(O(1)空間計算量)
function fibonacciDPOptimized(n) {
    if (n <= 1) {
        return n;
    }
    
    let prev2 = 0;  // F(i-2)
    let prev1 = 1;  // F(i-1)
    
    for (let i = 2; i <= n; i++) {
        const current = prev1 + prev2;
        prev2 = prev1;
        prev1 = current;
    }
    
    return prev1;
}

// 使用例
console.log(fibonacciDP(10));     // 55
console.log(fibonacciDP(50));     // 12586269025
console.log(fibonacciDP(100));    // 354224848179261915075

// DPテーブル全体を返す版
function fibonacciDPWithTable(n) {
    const dp = new Array(n + 1);
    dp[0] = 0;
    dp[1] = 1;
    
    for (let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    
    return { result: dp[n], table: dp };
}

⚖️ 再帰版との比較

再帰版(非効率)

  • • 時間計算量: O(2^n)
  • • 空間計算量: O(n)(コールスタック)
  • • n=40で約10億回の計算
  • • 同じ値を何度も再計算
  • • 実行時間が指数的に増加

DP版(効率的)

  • • 時間計算量: O(n)
  • • 空間計算量: O(n) または O(1)
  • • n=40でも40回の計算のみ
  • • 各値を一度だけ計算
  • • 実行時間が線形的に増加

💡 ポイント: 動的計画法は「部分問題の解を保存して再利用」することで、 計算の重複を避け、効率的にアルゴリズムを実行します。