Pythonでフィボナッチ数列を応用した階段の登り方を求解する

問題概要と考察

この問題では、n段の階段を1段または2段ずつ登る場合の、登り方の総数を求める必要があります。各段数における解を観察すると、フィボナッチ数列と同じパターンに従っていることが分かります。

  • 1段:1通り
  • 2段:2通り(1+1 または 2)
  • 3段:3通り(1+1+1、1+2、2+1)
  • 4段:5通り(1+1+1+1、1+1+2、1+2+1、2+1+1、2+2)

つまり、n段目までの登り方の総数は(n+1)番目のフィボナッチ数に該当します。

【アプローチ1】再帰による実装

シンプルな再帰関数を用いた実装です。ただし、この方法では計算量が指数関数的に増加するため、実用性は低いです。


def count_ways(n):
    if n == 0 or n == 1:
        return 1
    return count_ways(n - 1) + count_ways(n - 2)

step = int(input("段数を入力してください: "))
print(count_ways(step))

【アプローチ2】メモ化付き再帰

すでに計算済みの結果を保存することで、無駄な計算を省くことができます。


def count_ways_memo(n, memo=None):
    if memo is None:
        memo = {}
    if n == 0 or n == 1:
        return 1
    if n not in memo:
        memo[n] = count_ways_memo(n - 1, memo) + count_ways_memo(n - 2, memo)
    return memo[n]

step = int(input("段数を入力してください: "))
print(count_ways_memo(step))

【アプローチ3】動的計画法(DP)による実装

配列を使わず、2つの変数だけを使ってフィボナッチ数列を逐次計算します。


def count_ways_dp(n):
    a, b = 1, 1
    for _ in range(n - 1):
        a, b = b, a + b
    return a

step = int(input("段数を入力してください: "))
print(count_ways_dp(step))

【アプローチ4】行列の高速べき乗による解法

高速な行列累乗アルゴリズムを用いて、フィボナッチ数列の第n項を効率よく求めます。


def multiply_matrix(a, b):
    return [[a[0][0]*b[0][0] + a[0][1]*b[1][0],
             a[0][0]*b[0][1] + a[0][1]*b[1][1]],
            [a[1][0]*b[0][0] + a[1][1]*b[1][0],
             a[1][0]*b[0][1] + a[1][1]*b[1][1]]]

def matrix_power(matrix, n):
    result = [[1, 0], [0, 1]]  # 単位行列
    while n > 0:
        if n % 2 == 1:
            result = multiply_matrix(result, matrix)
        matrix = multiply_matrix(matrix, matrix)
        n //= 2
    return result

def count_ways_matrix(n):
    if n == 0 or n == 1:
        return 1
    matrix = [[1, 1], [1, 0]]
    power = matrix_power(matrix, n - 1)
    return power[0][0]

step = int(input("段数を入力してください: "))
print(count_ways_matrix(step))

タグ: Python アルゴリズム フィボナッチ数列 再帰 動的計画法

5月15日 04:00 投稿