【LeetCode] 509フィボナッチ

ポータル:[LeetCode] 509フィボナッチ

タイトル説明

フィボナッチ数は、通常、F(n)発現配列形態は呼ばれるフィボナッチ数列の数01、前の二つの図の背後に一人一人は、デジタルであり。それは次のとおりです。

F(0)= 0、F(1)= 1
+ F(N - 2) - F(N)= F(1 N)を、其中N> 1。

与えられたN計算F(N)

例1:

入力:2
出力:1
説明:F(2)= F( 1)+ F(0)= 1 + 0 = 1。

例2:

入力:3
出力:2
説明:F(3)= F( 2)+ F(1)= 1 + 1 = 2。

例3:

入力:4
出力:3の
説明:F(4)= F( 3)+ F(2)= 2 + 1 = 3。

ヒント:

  • 0≤ N≤30

分析とコード

  • 簡単に言えばフィボナッチ列は、前の2つの数の合計にそれぞれが等しい、最初の2つの数字に加えてあります。

再帰的なソリューション、

  • 再帰法は単純であるが、繰り返し計算が多数存在するのメモリを最適化するために使用することができます。

コード:

class Solution {
    public int fib(int N) {
        if (N <= 1) {
            return N;
        }
        return fib(N - 1) + fib(N - 2);
    }
}

ソリューション再帰のII思い出

  • 最適化手法のメモリが主に使用され加速するコンピュータプログラムの速度を、それがされて保存された関数呼び出しの高価な結果を、再度同じ入力でのキャッシュの結果を返します。
  • 計算は、計算の終了後、最初の直接の結果を返さないが、現在のNが鍵となるべきで、値にはHashMapに結果を保存し、かどうかを判断するために計算された前に、私たちの前の再帰に基づきます。

コード:

class Solution {
    Map<Integer, Integer> map = new HashMap<>();

    public int fib(int N) {
        if (N <= 1) {
            return N;
        }
        if (map.containsKey(N)) {
            return map.get(N);
        }
        int result = fib(N - 1) + fib(N - 2);
        map.put(N, result);
        return result;
    }
}

ソリューションスリー、動的計画

  • トップダウンのメモリアレイは、動的プログラミングアレイボトムアップの発生を置きます。

コード:

class Solution {
    public int fib(int N) {
        if (N <= 1) {
            return N;
        }
        int[] dp = new int[N + 1];
        dp[1] = 1;
        for (int i = 2; i <= N; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[N];
    }
}

4人用、ダイナミックプログラミング

  • さらにスペースを最適化するために、ちょうど2つの状態との関連レコードの2つだけの状態前の状態を計算します。

コード:

class Solution {
    public int fib(int N) {
        if (N <= 1) {
            return N;
        }
        int pre = 0, cur = 1;
        for (int i = 2; i <= N; i++) {
            int next = pre + cur;
            pre = cur;
            cur = next;
        }
        return cur;
    }
}

五、従来の行列乗算のソリューション

\ [\左\ {行列}は\左[\]右\ {行列} 1&0 \\ 0 0 \端{行列}始める開始[\ {{行列} 1&1 \\ 1&0 \端を開始マトリックス} \右] = \ \ [\ {行列} 1&1を開始左[\ =]右\ {行列} 1 + 0 1 + 0 \\ 0 + 0・0 + 0 \端{行列}開始左右\\ 0 0 \端{行列} \] \端{行列} \]

\ [\左\ {行列}は\左[\]右\ {行列} 1&1 \\ 0 0 \端{行列}始める開始[\ {{行列} 1&1 \\ 1&0 \端を開始マトリックス} \右] = \ \ [\ {行列} 2&1を開始左[\ =]右\ {行列} 1 + 1および1 + 0 \\ 0 + 0・0 + 0 \端{行列}開始左右\\ 0 0 \端{行列} \] \端{行列} \]

\ [\ {行列} \左[\開始{行列} F_n&F_ {N-1} \\ 0 0 \端{行列} \右] \左[\開始{行列} 1&1 \\ 1始まります&0 \端{行列} \右] = \ [\]右\ {行列} F_n + F_ {N-1}&F_n \\ 0 0 \端{行列}始める= \ [\ {始まる行列を左左右} F_ {N + 1}&F_n \\ 0 0 \端{行列} \] \端{行列} \]

  • 最初の2つの数字を有する行列の行、次いで\(\左[\ {始めるマトリックス} 1&\\ 1&0 1 \端{マトリックスは} \右] \) 次の行列を乗算することによって計算しました。

コード:

class Solution {
    public int fib(int N) {
        if (N <= 1) {
            return N;
        }
        int[][] matrix = { { 1, 0 }, { 0, 0 } };
        int[][] func = { { 1, 1 }, { 1, 0 } };
        for (int i = 2; i <= N; i++) {
            matrix = multiply(matrix, func);
        }
        return matrix[0][0];
    }

    private int[][] multiply(int[][] a, int[][] b) {
        int[][] c = new int[2][2];
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
            }
        }
        return c;
    }
}

ソリューション六、最適化マトリックス乗算

  • 一つの方法、ずつ毎回と同じマトリックス中に、すなわち、同じ番号はべき乗複数の乗算され、高速電力二分法に最適化することができ、また計算するために使用することができるマトリックス\を(M ^ { N- / 2} \) 次いで、マトリクス乗算を配合することができます。

    高速べき乗タイトル:[LeetCode] 50パウ(X、N)

  • 出発物質はもはや行列ではないが、マトリックスは\(\ [\マトリックスを開始{1}&マトリックスエンド{} \ 0 \\ 0 1 \右】左\)

  • この質問では、マトリックスは、最初の確認する必要があり、\(\左[\}マトリックスを開始{\\。1. 1&0.1&\マトリックスエンド{} \右] \) すなわちからF(2)始まり、マトリックスの構造を変更するために使用することができますされている\(\左[\ F_n開始{}&マトリックス-N-F_ {\\}。1. 1-N-F_ {}&-F_ {N-2} \}終了{マトリックス\右] \)そして、添字2は最初のものですので、渡すパラメータが1減少する必要があるため。

コード:

class Solution {
    public int fib(int N) {
        if (N <= 1) {
            return N;
        }
        int[][] matrix = { { 1, 1 }, { 1, 0 } };
        int[][] result = pow(matrix, N - 1);
        return result[0][0];
    }

    private int[][] pow(int[][] matrix, int n) {
        int[][] result = { { 1, 0 }, { 0, 1 } };
        for (int i = n; i > 0; i /= 2) {
            if ((i & 1) != 0) {
                result = multiply(matrix, result);
            }
            matrix = multiply(matrix, matrix);
        }
        return result;
    }

    private int[][] multiply(int[][] a, int[][] b) {
        int[][] c = new int[2][2];
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
            }
        }
        return c;
    }
}

ソリューション7つのフィボナッチ式

\ [F(N)= \ cfrac {((\ cfrac {1+ \のSQRT [2] {5}} {2})^ N - (\ cfrac {1- \のSQRT [2] {5}} {2 })^ N)}は{\ SQRT [2] {5}} \]

コード:

class Solution {
    public int fib(int N) {
        double sqrt5 = Math.sqrt(5);
        return (int) ((Math.pow((1 + sqrt5) / 2, N) - Math.pow((1 - sqrt5) / 2, N)) / sqrt5);
    }
}

ソリューション八、浮気

  • UH、最初のダイナミックプログラミングの方法によって、このような直接の数、最初の30で、次いで30 DPアレイ出力を生成します。
  • トピックそのN.の範囲

コード:

class Solution {
    public int fib(int N) {
        int[] result = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765,10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040 };
        return result[N];
    }
}

概要

動的プログラミング再帰テーブルへのメモリから多くの方法、再最適化、並びに行列乗算だけでなく、式を有するだけでなく、不正行為。


おすすめ

転載: www.cnblogs.com/qiu_jiaqi/p/LeetCode_509.html