🏔️ 階段昇降DP問題の詳細解析

📊 問題の概要と視覚化

n段の階段を1段または2段ずつ上る方法の数を求める問題です。これは動的プログラミング(DP)の典型的な例題です。

階段の視覚化(n=5の例)

地面
1段
2段
3段
4段
5段

🧮 漸化式の導出過程

Step 1: 問題の分析

n段目に到達する方法は以下の2つに分類できます:

  • 方法1: (n-1)段目から1段上る
  • 方法2: (n-2)段目から2段上る

Step 2: 漸化式の構築

dp[i] = i段の階段を上る方法の数とすると:

dp[n] = dp[n-1] + dp[n-2] // 初期条件 dp[0] = 1 // 何もしない方法が1通り dp[1] = 1 // 1段上る方法が1通り

🔍 具体例による計算過程(n=6)

インタラクティブ計算デモ



DP配列の状態

各段への到達方法

💾 メモリ最適化の解析

通常版

空間計算量: O(n)

配列全体を保持

メモリ使用量: n × 8バイト

最適化版

空間計算量: O(1)

前の2つの値のみ保持

メモリ使用量: 2 × 8バイト

// 最適化版のコード構造 let prev2 = 1; // dp[i-2] let prev1 = 1; // dp[i-1] let current; for (let i = 2; i <= n; i++) { current=prev1 + prev2; // dp[i]=dp[i-1] + dp[i-2] prev2=prev1; // 値を更新 prev1=current; }

🌀 フィボナッチ数列との関係

この問題の答えは実際にはフィボナッチ数列と密接な関係があります:

F(0) = 1, F(1) = 1, F(2) = 2, F(3) = 3, F(4) = 5, F(5) = 8, ... 階段: 1, 1, 2, 3, 5, 8, ... dp[n] = F(n+1) // フィボナッチ数列のn+1番目

これは偶然ではなく、問題の構造が本質的にフィボナッチ数列の定義と同じだからです。

⚡ 計算量解析

時間計算量

O(n)

各段について1回ずつ計算

n=40の場合: 40回の演算

空間計算量

O(1) (最適化版)

定数個の変数のみ使用

nに依存しない固定サイズ

🎯 実装のポイント

1. エッジケースの処理

if (n === 0) return 1; // 基底ケース if (n === 1) return 1; // 基底ケース

2. 整数オーバーフローの考慮

JavaScriptでは数値が53ビット精度なので、n≤40では問題なし

// n=40の場合の答え: 165,580,141 // JavaScript の Number.MAX_SAFE_INTEGER: 9,007,199,254,740,991

3. パフォーマンス測定

const startTime = process.hrtime.bigint(); // 処理実行 const endTime = process.hrtime.bigint(); const executionTime = Number(endTime - startTime) / 1000000; // ms