Pythonで合計がnとなるフィボナッチ数の最小個数を求めるプログラム
問題の概要
ある整数 n が与えられたとき、その合計がちょうど n になるようにするために必要なフィボナッチ数の最小個数を求めます。
たとえば、入力が n = 20 の場合、出力は 3 になります。これは、フィボナッチ数列に含まれる [2, 5, 13] の3つの数を足し合わせることで 20 を作れるためです。
解決のためのアルゴリズム
この問題は「貪欲法(グリーディ法)」を用いることで効率的に解けます。基本的な考え方は、「n 以下の最大のフィボナッチ数を選び、n から引く」という操作を n が 0 になるまで繰り返すというものです。
res := 0(使用したフィボナッチ数のカウント用変数)
fibo := 初期値 [1, 1] を持つリスト
fibo の最後の要素が n 以下である間、次を繰り返す
x := fibo の末尾2つの要素の合計
x を fibo に追加する
n が 0 でない間、次を繰り返す
fibo の最後の要素が n より大きい間、末尾の要素を削除する
n := n − fibo の最後の要素
res := res + 1
res を返す
この貪欲法が正しく機能する背景には、ゼッケンドルフの定理があります。すべての正の整数は、連続しないフィボナッチ数の和として一意に表すことができ、各ステップで「n 以下の最大のフィボナッチ数」を採用することで、必要な項数が最小になります。
Pythonでの実装例
class Solution:
def solve(self, n):
res = 0
fibo = [1, 1]
while fibo[-1] <= n:
fibo.append(fibo[-1] + fibo[-2])
while n:
while fibo[-1] > n:
fibo.pop()
n -= fibo[-1]
res += 1
return res
ob = Solution()
n = 20
print(ob.solve(n))
入力
20
出力
3
処理の流れの解説
まず最初の while ループで、n を超えない範囲でフィボナッチ数列を生成します(1, 1, 2, 3, 5, 8, 13, 21 …)。次に、n が 0 になるまで、n 以下の最大のフィボナッチ数を順に引いていきます。
n = 20 の場合の流れは以下の通りです。
21 は 20 を超えるため削除され、13 を選択 → 残り 7
8 は 7 を超えるため削除され、5 を選択 → 残り 2
2 を選択 → 残り 0
このように 3 回の引き算で完了するため、答えは 3 となります。計算量はフィボナッチ数列の生成に O(log n)、残りの処理も同程度であり、非常に効率的な手法です。
-
Pythonで数の因子の最小合計を求めるプログラム|素因数分解の考え方
本記事では、与えられた整数について、積が元の数と等しくなる因子の組み合わせの中から合計が最小となる値を求める方法を、Pythonのコード例とともに解説します。 問題定義 入力として1つの整数が与えられます。この数を複数の因子の積として表したとき、因子の合計が最小になるケースを求めてください。 すべての因子の組み合わせを網羅的に調べて合計を比較する方法もありますが、実はもっとシンプルで効率的なアプローチが存在します。 考え方:素因数の合計が最小になる 鍵となるのは次の性質です。積が一定の値になるとき、因子の合計が最小になるのは、すべての因子を素数まで分解した場合(素因数分解した場合)です。
-
Pythonでフィボナッチ数を求める方法:再帰と動的計画法の2つのアプローチを徹底解説
本記事では、「n番目のフィボナッチ数を計算する」という問題に対する解決策と考え方を、2つの異なるアプローチ(再帰的手法と動的計画法)のコード例とともにわかりやすく解説します。 問題の概要 今回の課題は、n番目のフィボナッチ数を求めることです。 フィボナッチ数列 Fn は、次の漸化式によって定義されます。 Fn = Fn-1 + Fn-2 初期値(シード値)は以下の通りです。 F0 = 0、F1 = 1 この問題を解くには、主に次の2つの方法があります。 再帰的なアプローチ 動的計画法によるアプローチ アプローチ1:再帰的な手法 まずは、定義そのものをそのままコードに反映させた再帰的な実