Algorithm Basis: Dynamic Programming

Table of contents

The Zen of Dynamic Programming

Solving Fibonacci Sequences in Various Latitudes

What is the Fibonacci sequence

naive recursive scheme

naive recursion problem

Fib Top-Down, Memorandum Scheme

Fib bottom-up method


The Zen of Dynamic Programming

Dynamic programming is the most interesting part of the basic part of the algorithm. I have been thinking for many days, how to summarize dynamic programming in a few short words like the previous algorithm summary, and then give some questions for everyone to practice for mastery Take this knowledge completely.

Then I found that, like the greedy strategy, dynamic programming is not a fixed routine, but a kind of thought: [Use past accumulation to solve current problems]. I call this thought the Zen of dynamic programming.

Solving Fibonacci Sequences in Various Latitudes

What is the Fibonacci sequence

Fibonacci can be generalized with a string of numbers:

1,1,2,3,5,8,....,num[n-1],num[n],num[n-1]+num[n]

The following is its recursive structure, namely num[n] = num[n-1] + num[n-2] if n >= 2

naive recursive scheme

We can use this rule to make a program to calculate the size of the Nth value in a very simple way:


int fib(int n) {
    if(n<=0) return 0;
    if(n<=2) return 1;
    return fib(n-1) +fib(n-2);
   
}

Here is the execution structure of this program:

 We decompose a problem of size N into two problems of size N-1 and N-2, and then continue to divide until the problem becomes a solved problem, such as falling to fib(1), fib( 2) on.

naive recursion problem

Then when we actually execute this code, we will find that once the value we seek becomes larger, the time required for calculation will become very large! This is related to our time complexity. It is not difficult to see the above tree. If each node represents that we want to calculate once, then we need to calculate 2^(n -1) times.

We need to study what is the problem with this tree. It is obvious that there are too many repeated calculations. Every time a fib(x) is calculated, the value must be traced back to fib(1) and fib(2). Is there any way to Should the value calculated before be used directly? rather than recalculating it again.

Fib Top-Down, Memorandum Scheme

This time we apply for a space of size N before the algorithm starts. This space is used to record the calculated value. When it is used again later, the value in the cache space is directly used instead of recalculated.

The cache is somewhat similar to the memo we usually use, and the calculation is also top-down, so this method is also called the top-down method or the memo method.

code show as below:

int _fib(int n, int* cache) {
   if(n<=0) return 0;
   if(n<=2) return 1;
   int num1 = 0;
   int num2 = 0;
   if(cache[n-1] != -1) {
    num1  = cache[n-1];
   }
   else {
    num1 = _fib(n-1);
    cache[n-1] = num1;
   }
   if(cache[n-2] !=-1)
   {
    num2 = cache[n-2];
   }
   else {
    num2 = _fib(n-2);
    cache[n-2] = num2;
   }
   return num1 + num2;

}
int fib(int n) {
    int *cache = (int*)malloc(sizeof(int)*n);
    for(int i =0;i<n;i++) {
        cache[i] = -1;
    }
    return _fib(n, cache);
    
}

Fib bottom-up method

Because Fibonacci is known on a small scale, and larger scales can be obtained based on fib(1) and fib(2), it can be realized using the bottom-up method.

That is to say, to find fib(n), calculate fib(3) from fib(1)+fib(2), and then get fib(4) from fib(2)+fib(3), until fib(n) .

Here is the code:

int fib(int n) {
    if (n<=0) return 0;
    if (n<=2) return 1;
    int num1 = 1;
    int num2 = 1;
    for(int i = 2;i<n;i++) {
       int tmp = num1+num2;
       num1 = num2;
       num2 = tmp;
    }
    return num2;
}

Guess you like

Origin blog.csdn.net/qq_32378713/article/details/128109447