フィボナッチ列は、列1の数、1、2、3、5、8、13、21、34、55、89、144、233,377,610,987,1597,2584,4181,6765を指し、10946,17711,28657,46368 ......
私は数が例の外になるはずですフィボナッチC言語、大学教員は、多くの場合、いくつかの一般的な数学の問題と再帰を使用しての話をし、学習を覚えています。後の作品では、就職の面接は、フィボナッチ金額欄が評価アルゴリズムを記述するために大きな可能性があることを、時間の問題に直面しています。私はすべてのプログラマは間違いなく一つのことを行いますアルゴリズムフィボナッチ列を書き、私たちの道路プログラムにそれを言うことができます。昨日は、活動が主催テンセント教室活動がゲストを持って次の行に移動するには、教室、講師のアルゴリズムコースの創設者である、我々は問題の私の認識を覆すものと考え、この問題、について話しました。本論文では、アルゴリズムを達成するために、問題を分析し、整理して、これらの講師を説明するために従いました。
以下に、我々はいくつかの一般的な分析アルゴリズムと効率性を見てください。
1、再帰
観察を通じて、我々は最初の2つの値のそれぞれは、基本的には再帰共通を使用して実装されます、私たちのように多くの合計である後ろ法の一つは、第1項と第2項の値は、1であることを見つけます次のようなアルゴリズムは次のようになります。
1つの 公共 int型 FIB(int型N){ 2 であれば(N == 1 || N == 2 ){ 3 リターン 1 。 4 } 5 リターン FIB(N - 2)+ FIB(N - 1 )。 6 }
このコードは非常にシンプルかつエレガントに見える、私は、著者がそのように書かれている前に、私たちのほとんどはまた、通常は、ここで書かれていると思いますし、私の知識では、唯一の埋蔵量がありますこのようなアルゴリズムを意識。
nは実装するための再帰的方法では、依然として比較的小さい実際に問題はないが、例えば、N = 45のため、我々は、テストコードの実行によって、その結果を見たときにnがわずかに大きいとき:
1 MyClassのMYCLASS = 新しいMyClassの()。 2 長い T1 = にSystem.currentTimeMillis(); 3 INT N = 45 。 4 int型の結果= myClass.fib(N)。 5 長い T2 = にSystem.currentTimeMillis(); 6のSystem.out.println( "N =" + N + ";結果=" +結果+ ";時間=" +(T2 - T1))。
得られた結果は以下のとおりです。
N = 45;結果= 1134903170;時間= 2881
私たちは、このコードの実装は、費やした時間は2881msであることがわかりました。値が大きい場合、nは= 48:
N = 48;結果= 512559680;時間= 11746
以上11Sに達するまでの時間!nは指数関数的な成長に消費された時間後、わずかに大きい場合には、例えば、n = 64、時間は二、三世紀を消費することができます!それを信じてはいけない、読者が試すことができます!
だから、それは非常にひどいです、私たちは何の問題は、実際に両方のシンプルかつエレガントなアルゴリズムを見えないので、時間がかかり考え、それは単にいくつかのゴミコードです。
我々は、一例として、N = 6のアルゴリズムの実装を分析するために、単純なマップを使用します。
私たちは、F(n)は、このメソッドは何度も呼ばれ、ここで繰り返し率は、それが二重にカウントnがわずかに大きい木が非常に大きくなりであれば、何回もあり、非常に高いことがわかります。ここでは、各ノードが一度計算される必要があり、数は、バイナリツリーのノードの合計数を計算し、その時間複雑さを示すことO(2であることが確認できN-空間複雑バイナリツリーである、指数関数的です)高さは、O(N)です。このように、私たちはなぜ、このコード効率非常に低いバーを明確にする必要があります。
2、配列保存法(名前は独自のコマンドです)
繰り返し何度も回避するために、あなたは、n = 1から計算される起動することができ、アレイに必要な最終値から直接採取格納された配列、と計算されたデータのそれぞれは、アルゴリズムは以下の通りであります:
1つの 公共 int型 FIB(int型N){ 2 INT [] FIB = 新しい INT [N]。 3 FIB [0] = 1 。 4 FIB [1] = 1 。 図5は、 のために(int型 I = 2、iがn <; iは++ ){ 6 FIB [I] = FIB [I - 2] + FIB [I - 1 ]。 7 } 8 戻り FIB [N - 1 ]。 9 }
また、撮影したN = 45とn = 48の結果を見てました
N = 45;結果= 1134903170;時間= 0
N = 48;結果= 512559680;時間= 0
消費時間は0である(私はここに来る時間はミリ秒レベルの精度で、1ms以下の前後の時間差なので、ここで算出された結果は、実際の時間がかかり、ゼロではなく、0、フォローアップの詳細には触れません)、あなたは実行を見ることができます効率は、多くのことを改善しました。メインループのアルゴリズムは、時間計算量はO(n)は、空間複雑さも大幅に上記のアルゴリズムに基づいて、O(N)であるので、長さnの配列の周期を開放する必要があります効率を向上させます。
3、変数保存法(また、独自の命名)
上記のアルゴリズムは非常に効率的であるが、我々はまだ問題を見つけますが、実際には、配列全体では、唯一、最新の三つの値それぞれの計算、それはもはや必要とされた後、前の計算の値を必要とします。例えば、10の計算は、配列空間は、最初の2つの空間8と9、もはや必要実際には前方空間7に最初に必要とされます。だから我々はまた、三つの変数は、以下のアルゴリズムによって保存されたデータを向上させることができます。
1つの 公共 int型 FIB(int型N){ 2 INT第= 1 。 3 INT = 1秒。 4 int型の第= 2 。 5 ため(int型、iがn = <; I = 3 iは++ ){ 6 第=第一+ 第二; 7 第= 秒; 8 第二= 第三; 9 } 10 リターン第三; 11 }
まだ時間複雑度はO(n)、空間的複雑度3は、空間複雑さが0であるので、この方法は非常に効率的である、すなわち、一定です。
4、公式法
実際には、フィボナッチ数を求めると、値の式を有します:
アルゴリズムは、この式で実現することができます。
1つの 公共 int型 FIB(int型N){ 2 二重 C = Math.sqrt(5 )。 3 リターン(INT)((Math.pow((1 + C)/ 2、N) - Math.pow((1 - C)/ 2、N))/ C)。 4 }
その時の複雑さと空間の複雑さは、これらの数式を達成JDKに依存し、効率が非常に高いです。
N = 48;結果= 512559680;時間= 0
上記の分析を通じて、我々はフィボナッチ列は、あなたが実際の状況に応じて第一及び第四の三種類を選択することができアルゴリズムを記述します。
読者が間違って説明し、この記事や、間違った場所を見つけた場合は、どうもありがとうございました、私たちに知らせてください!