web-dev-qa-db-ja.com

O(1)時間で実行するフィボナッチ関数を記述できますか?

ですから、フィボナッチの質問がたくさんあります。私は個人的に、彼らを嫌います。たくさん。たくさん以上。誰もが二度と面接の質問として使えないようにできたらいいなと思いました。 O(1)にどれだけフィボナッチを得ることができるか見てみましょう。

これが私のキックオフです。ウィキペディアからのベビーベッドですが、もちろん十分な余裕があります。重要なことに、このソリューションは特に大きなfibに対して爆発し、べき関数の比較的単純な使用法が含まれています。これにより、ライブラリが最悪の場合、O(log(n))になります。良くないです。べき関数を取り除くか、少なくともそれを専門化できると思います。誰か助けてくれませんか?有限以外に真のO(1)解決策はありますか? *ルックアップテーブルを使用するソリューション?

http://ideone.com/FDt3P

#include <iostream>
#include <math.h>
using namespace std; // would never normally do this.

int main()
{
int target = 10;
cin >> target;
// should be close enough for anything that won't make us explode anyway.
float mangle = 2.23607610; 

float manglemore = mangle;
++manglemore; manglemore = manglemore / 2;
manglemore = pow(manglemore, target);
manglemore = manglemore/mangle;
manglemore += .5;
cout << floor(manglemore);

}

*私は知っています、私は知っています、それはフィボナッチが持っているゼロの実用的な使用のどれにも十分です。

27
Jake Kurzer

任意の大きな入力が与えられた場合、nを読み取るだけでO(log n)が必要になるため、その意味で一定時間のアルゴリズムは不可能です。したがって、適切なパフォーマンスを得るには、閉じた形式のソリューションを使用するか、気になる値を事前に計算してください。

編集:コメントでは、フィボナッチはO(phi^n)印刷であるため、実際にはもっと悪いことが指摘されました結果フィボナッチのO(log (phi^n))O(n)

18
Philip JF

これは、フィボナッチ数列項のほぼO(1)の解です。確かに、O(log n)はシステムのMath.pow()の実装によって異なりますが、インタビュアーがそれを探しているのであれば、目に見えるループのないフィボナッチです。 ceil()は、.9の繰り返しを返す大きな値の丸め精度が原因でした。

enter image description here

JSの例:

function fib (n) {
  var A=(1+Math.sqrt(5))/2,
      B=(1-Math.sqrt(5))/2,
      fib = (Math.pow(A,n) - Math.pow(B,n)) / Math.sqrt(5);
      return Math.ceil(fib);
}
49
Joseph Lust

次の回答はO(1)でを実行しますが、それがあなたの質問に適しているかどうかはわかりません。 テンプレートメタプログラミング と呼ばれます。

#include <iostream>
using namespace std;

template <int N>
class Fibonacci
{
public:
    enum {
        value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value
    };
};

template <>
class Fibonacci<0>
{
public:
    enum {
        value = 0
    };
};

template <>
class Fibonacci<1>
{
public:
    enum {
        value = 1
    };
};

int main()
{
    cout << Fibonacci<50>::value << endl;
    return 0;
}
15
Dante May Code

プログラミング:アルゴリズムの導出では、Anne Kaldewaijが展開します 線形代数解 取得(プログラミングから変換およびリファクタリング)その本で使用されている言語):

template <typename Int_t> Int_t fib(Int_t n)
{
    Int_t a = 0, b = 1, x = 0, y 1, t0, t1;
    while (n != 0) {
        switch(n % 2) {
            case 1:
                t0 = a * x + b * y;
                t1 = b * x + a * y + b * y;
                x = t0;
                y = t1;
                --n;
                continue;
            default:
                t0 = a * a + b * b;
                t1 = 2 * a * b + b * b;
                a = t0;
                b = t1;
                n /= 2;
                continue;
        }
    }
    return x;
}

これにはO(log n)の複雑さがあります。もちろん、これは一定ではありませんが、特に比較的高速な整数演算のみを使用し、丸め誤差の可能性がないことを考えると、議論に追加する価値があると思います。

5
Max Lybbert

処理する最大値を選択してください。それより大きい値の場合、エラーが発生します。それよりも小さい値の場合は、その小さい値で回答を保存し、「最大」値の計算を実行し続け、保存された値を返します。

結局のところ、O(1)は具体的には「高速」ではなく、「一定」を意味します。この方法では、すべての計算に同じ時間がかかります。

1
evil otto

はい。値を事前に計算し、配列に格納してから、Nを使用してルックアップを実行します。

1
EvilTeach

O(1)空間と時間(Python実装)のフィボナッチ:

PHI = (1 + sqrt(5)) / 2

def fib(n: int):
  return int(PHI ** n / sqrt(5) + 0.5)
0
CCBet