[Dynamic programming] Fibonacci sequence


Regarding the Fibonacci sequence, I believe that friends who have learned function recursion must know what it is, but in order to strengthen the ideological study of dynamic programming, I have opened a new topic - dynamic programming, which will be briefly introduced here. The idea of ​​dynamic programming, use this idea to open an efficient solution to the Fibonacci sequence, and start with this example to deeply explore and learn dynamic programming.

What is dynamic programming?

To explain in human words is 大事化小,小事化了the 分治thought

Ok, I seem to have seen this before. Yes, when learning function recursion, this idea is used, but the difference is that dynamic programming is in the process of divide and conquer 对小问题处理好的结果进行了保存,等到之后在处理更大规模问题时可以直接使用这些结果, instead of seeking the largest each time. When it comes to problems, start with small problems and ask for big problems.

Four angles to think about the problem specifically:

  1. state definition
  2. Definition of transition equation between states
  3. state initialization
  4. return result

Take this case for example!

Bull link

Mathematically, the Fibonacci sequence is defined recursively as follows: F (0)=0, F (1)=1, F (n)= F (n - 1)+ F (n - 2 ) ( n ≥ 2, n ∈ N*) to find the Nth Fibonacci sequence

recursive thinking

If you use recursive thinking to find, it is very simple, it should be like this:

public class Solution {
    
    
    public int Fibonacci(int n) {
    
    
        if(n <= 0) {
    
    
            return 0;
        }
        //边界条件
        if(n == 1 || n == 2) {
    
    
            return 1;
        }
        //按照定义总结出的递归式
        return Fibonacci(n - 1) + Fibonacci(n - 2);
    }
}

Although the code is simple, when n is larger, the amount of operations involved will explode exponentially.

insert image description here

As can be seen from the figure, when the value of n is small, the calculation is very simple, but when the value of n becomes large, a large number of repeated calculations will occur. When n is 5, Fib(1) has been 2 times. Participating in the operation, Fib(2) has already participated in the operation 3 times, and Fib(3) has been repeatedly calculated twice. It is conceivable that when n becomes larger, the amount of repeated calculation will increase greatly, and the calculation speed will be increased. It will be visibly slower with the increase of n, and the program will even hang.

Therefore, if the small problems calculated each time are stored, the efficiency can be greatly improved. We can prepare an array to store the results of the small problems!

moving thought

State definition: The value of Fib(i) is the i-th value of the Fibonacci sequence

Definition of transition equation between states: Fib(i) = Fib(i - 1) + Fib(i - 2)

State initialization: Fib(0) = 0 Fib(1) = 1

Return result: Return the value of Fib(n), which is the nth value of the Fibonacci sequence

public class Solution {
    
    
    public int Fibonacci(int n) {
    
    
        if(n == 1||n == 2) return 1;
        if(n <= 0) return 0;
        int[] Fib = new int[n + 1]; //用来存放每次计算出的斐波那契数
        Fib[0] = 0;
        Fib[1] = 1; //状态的初始化
        Fib[2] = 1;
        for(int i = 3;i <= n;i ++) {
    
    
            Fib[i] = Fib[i - 1] + Fib[i - 2]; //转移方程
        }
        return Fib[n]; //返回所求的第n位斐波那契数
    }
}

Moving back to the thought (improvement)

According to the requirements of the title, in fact, we only need to know the first two items of the nth item. It is not necessary to put all the medians of the Fibonacci sequence smaller than n into the array, only in the process of looping Continuously update n - 1, n - 2 is the value of the Fibonacci number.

public class Solution {
    
    
    public int Fibonacci(int n) {
    
    
        if(n == 1||n == 2)return 1;
        if(n <= 0) return 0;
        int ret = 0;
        int n1 = 1; //n - 1位的初始值
        int n2 = 1; //n - 2位的初始值
        for(int i = 3;i <= n;i ++) {
    
    
            ret = n1 + n2; //转移方程
            n2 = n1;       //更新n - 2位的值
            n1 = ret;      //更新n - 1位的值
        }
        return ret;        //返回结果
    }
}

Finish!

Guess you like

Origin blog.csdn.net/weixin_46103589/article/details/121865054