Fibonacci problem and extension

Author: Grey

Original address: Fibonacci problem and extension

Introduction to Fibonacci sequence

Fibonacci numbers are usually represented by F(n), and the sequence formed is called Fibonacci sequence. The sequence starts with 0 and 1, and each subsequent number is the sum of the first two numbers. That is:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2), where n > 1

Reference for related topics: LeetCode_0509_FibonacciNumber

thinking

Violence solution: recursive version

    public static int fib(int N) {
        if (N <= 0) {
            return 0;
        }
        if (N == 1 || N == 2) {
            return 1;
        }
        return fib(N - 1) + fib(N - 2);
    }

Violence solution: iterative version

    public static int fib2(int N) {
        if (N <= 0) {
            return 0;
        }
        if (N == 1 || N == 2) {
            return 1;
        }
        int first = 1;
        int second = 1;
        int result = 0;
        for (int i = 3; i <= N; i++) {
            result = first + second;
            first = second;
            second = result;
        }
        return result;
    }

Optimal solution

If a recursion, in addition to the initial item, has the following form

F(N) = C1 * F(N) + C2 * F(N-1) + ... + Ck * F(N-k) ( C1...Ck and k Are constants)

Moreover, the recursive expression is strict and does not transfer with conditions, so there is an optimization similar to Fibonacci sequence, and the time complexity can be optimized to O(logN),

General term formula of Fibonacci sequence

F(N) = F(N - 1) + F(N - 2)

Any term of Fibonacci sequence (take F2, F3 and F4 as examples) has the following formula:

|F2,F3| * |a,b| = |F3,F4|
          |c,d|

Where a = 0, b = 1, c = 1, d = 1 in the matrix

So for item N of Fibonacci, there are

|F(N),F(N-1)|  = |F2,F1| * |0,1| ^ (N - 2)
                           |1,1| 

Therefore, the key to optimization is how to find the (N - 2) power of a matrix faster. We can refer to how to find the N - power of an integer fastest, which can be calculated by fast power.

For example:

Find the 5th power of 6

You can ask this,

First convert 5 into binary 0101, prepare a variable t, which is initially equal to 6, and prepare a variable ans, which is initially equal to 1,

Traverse the binary bits of 5 from right to left,

If 1 is encountered: ans *= t and t *= t,

If 0 is encountered, you don't need to process ans, just t *= t,

Until the binary bit of 5 is traversed, ans is the answer, and the whole complexity is O(logN),

For details, please refer to: The n-th power of x , code:

public class LintCode_0428_PowXN {

    // fabanacci like problem
    // POW x n (n to binary)
    // Complexity log (N)
    public static double myPow(double x, int n) { 
        int pow = Math.abs(n == Integer.MIN_VALUE ? n + 1 : n);
        double ans = 1D;
        double t = x;
        while (pow != 0) {
            if ((pow & 1) != 0) {
                ans *= t;
            }
            pow >>= 1;
            t *= t;
        }
        if (n == Integer.MIN_VALUE) {
            ans *= x;
        }
        if (n < 0) {
            ans = 1D / ans;
        }
        return ans;
    }
}

Back to the Fibonacci sequence problem, the N-th power of a matrix can also be optimized into the solution of O(logN). In the Fibonacci problem, the ans variable is initially the unit matrix, that is:

|1,0| 
|0,1| 

t in the Fibonacci problem, the initial value is

|0,1| 
|1,1| 

Logic is the same as finding the X-Power of N, except that t and ans variables in the X-Power of N are digital multiplication, while Fibonacci problem is matrix multiplication. For the rules of matrix multiplication, please refer to the knowledge of linear algebra. The complete code is as follows

    // Optimal solution O(log^N)
    public static int fib3(int N) {
        if (N <= 0) {
            return 0;
        }
        if (N == 1 || N == 2) {
            return 1;
        }
        int[][] matrix = matrixPow(new int[][]{{0, 1}, {1, 1}}, N - 2);
        return matrix[0][1] + matrix[1][1];
    }

    public static int[][] matrixPow(int[][] matrix, int n) {
        int[][] ans = new int[][]{{1, 0}, {0, 1}};
        int[][] t = matrix;
        while (n != 0) {
            if ((n & 1) != 0) {
                ans = matrix(t, ans);
            }
            n >>= 1;
            t = matrix(t, t);
        }
        return ans;
    }

    public static int[][] matrix(int[][] A, int[][] B) {
        int[][] result = new int[2][2];
        result[0][0] = A[0][0] * B[0][0] + A[0][1] * B[1][0];
        result[0][1] = A[0][0] * B[0][1] + A[0][1] * B[1][1];
        result[1][0] = A[1][0] * B[0][0] + A[1][1] * B[1][0];
        result[1][1] = A[1][0] * B[0][1] + A[1][1] * B[1][1];
        return result;
    }

Fibonacci like problems can be calculated by the above optimization method,

For example, the general term formula of item N of a problem is:

F(N) = 6 * F(N-1) + 3 * F(N-5)

Then, the value of the nth item can be converted into the following matrix formula,

|Fn,Fn-1,Fn-2,Fn-3,Fn-4| = |F5,F4,F3,F2,F1|x|5x5|^(N-5)

List the first several items and bring them in to find the number of each position in the 5 times 5 matrix, and then refer to the fast power algorithm to solve it.

Fibonacci like sequence problem

Cow problem

Step climbing problem

Tiling problem

01 number of strings

When can't we use the relevant formula of Fibonacci problem

Note: if there is conditional transfer, the relevant formula of Fibonacci like problem cannot be used, for example: Code_0056_ConvertToLetterString.java

more

Algorithm and data structure notes

reference material

Tags: Algorithm data structure leetcode

Posted on Wed, 01 Dec 2021 20:03:45 -0500 by SoN9ne