Make it work, make it right, make it fast. —— Kent Beck
Here the first two sentences say is recursive, that is to say after one iteration. Have to admit recursive Dafa really easy to write, but iterative method is more efficient and fast.
Dynamic programming, may sound strange, but in other words, a recursive come to the preliminary conclusion after write with iterative manner.
Take the classic Fibonacci sequence for instance
long long fibonacci(int n){
if(n == 0){ return 1; } else if(n == 1){ return 1; } else{ return fibonacci(n - 1) + fibonacci(n - 2); } }//T(n) = pow(2, n - 1) = O(pow(2, n))
We accordingly wish to trace recursion:
We can see in this recursive tree has a lot of duplicate branches, so if we can cut to duplicate branch?
Improved First: Memory of recursive
long long fibonacci(int n){ long long f[100] = {0}; if(n == 0){ return f[0] = 0; } else if(n == 1){ return f[1] = 1; } else if(f[n]){ return f[n]; } else{ return f[n] = fibonacci(n - 1) + fibonacci(n - 2); } }//T(n) = pow(2, n - 2) = O(pow(2, n))
Although deleting duplicate branches, but the complexity does not seem to fall much
Improved II: dynamic programming (non-recursive)
long long fibonacci(int n){ long long f[100]; f[0] = 0; f[1] = 1; for(int i = 2; i <= n; i++){ f[i] = f[i - 1] + f[i - 2]; } return f[n]; }//T(n) = O(n)
This algorithm change from top to bottom, two above ideas while taking a bottom-up way of thinking, thinking we usually prefer to solve the problem (iteration).
And it should also be photographed I said at the beginning of dynamic programming is to use a recursive come to the preliminary conclusion was converted into the form of iteration.
Mentioned dynamic programming, a classic example is:
LCS (Longest Common Subsequence) // longest common subsequence
Sequence: character string is extracted several letters arrayed in the order is extracted from a string
Longest common subsequence: two common subsequence longest
eg: d i d a c
a d v a n
Longest common subsequence: da
Faced with this problem, our conventional thinking is:
1. Identify common subsequence
2. And then find out where the longest common subsequence
Dynamic programming idea is:
Imagine all the sub-problems into a matrix
Matrix meet:
(1) if( i == 0 || j == 0 ) A[i][j] = 0
(2) if( i,j > 0 && Ci == Rj ) A[i][j] = A[i - 1][j - 1] + 1
(3) if( i,j > 0 && Ci != Rj ) max( A[i][j - 1], A[i - 1][j] )
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <string> using namespace std; int main(){ string str1 = "didac"; string str2 = "advan"; int A[7][7] = {0}; int longest = 0; for(int i = 0; i <= str1.length(); i++){ for(int j = 0; j <= str2.length(); j++){ if(i == 0 || j == 0){ A[i][j] = 0; } else if(i > 0 && j > 0 && str1[i - 1] == str2[j - 1]){ A[i][j] = A[i - 1][j - 1] + 1; } else if(i > 0 && j > 0 && str1[i - 1] != str2[j - 1]){ A[i][j] = max(A[i - 1][j], A[i][j - 1]); } } } for(int i = 0; i <= str1.length(); i++){ for(int j = 0; j <= str2.length(); j++){ cout << A[i][j]; } cout << endl; } return 0; }
Summary: Whether it is from the table view, or from the point of view matrix rule, the length of the common subsequence that is the largest element in the matrix, and the smallest increase in the minimum number of first elements of a common sequence is the element number of columns and rows.
long long fibonacci(int n){
if(n == 0){ return 1; } else if(n == 1){ return 1; } else{ return fibonacci(n - 1) + fibonacci(n - 2); } }//T(n) = pow(2, n - 1) = O(pow(2, n))
We accordingly wish to trace recursion:
We can see in this recursive tree has a lot of duplicate branches, so if we can cut to duplicate branch?
Improved First: Memory of recursive
long long fibonacci(int n){ long long f[100] = {0}; if(n == 0){ return f[0] = 0; } else if(n == 1){ return f[1] = 1; } else if(f[n]){ return f[n]; } else{ return f[n] = fibonacci(n - 1) + fibonacci(n - 2); } }//T(n) = pow(2, n - 2) = O(pow(2, n))
Although deleting duplicate branches, but the complexity does not seem to fall much
Improved II: dynamic programming (non-recursive)
long long fibonacci(int n){ long long f[100]; f[0] = 0; f[1] = 1; for(int i = 2; i <= n; i++){ f[i] = f[i - 1] + f[i - 2]; } return f[n]; }//T(n) = O(n)
This algorithm change from top to bottom, two above ideas while taking a bottom-up way of thinking, thinking we usually prefer to solve the problem (iteration).
And it should also be photographed I said at the beginning of dynamic programming is to use a recursive come to the preliminary conclusion was converted into the form of iteration.
Mentioned dynamic programming, a classic example is:
LCS (Longest Common Subsequence) // longest common subsequence
Sequence: character string is extracted several letters arrayed in the order is extracted from a string
Longest common subsequence: two common subsequence longest
eg: d i d a c
a d v a n
Longest common subsequence: da
Faced with this problem, our conventional thinking is:
1. Identify common subsequence
2. And then find out where the longest common subsequence
Dynamic programming idea is:
Imagine all the sub-problems into a matrix
Matrix meet:
(1) if( i == 0 || j == 0 ) A[i][j] = 0
(2) if( i,j > 0 && Ci == Rj ) A[i][j] = A[i - 1][j - 1] + 1
(3) if( i,j > 0 && Ci != Rj ) max( A[i][j - 1], A[i - 1][j] )
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <string> using namespace std; int main(){ string str1 = "didac"; string str2 = "advan"; int A[7][7] = {0}; int longest = 0; for(int i = 0; i <= str1.length(); i++){ for(int j = 0; j <= str2.length(); j++){ if(i == 0 || j == 0){ A[i][j] = 0; } else if(i > 0 && j > 0 && str1[i - 1] == str2[j - 1]){ A[i][j] = A[i - 1][j - 1] + 1; } else if(i > 0 && j > 0 && str1[i - 1] != str2[j - 1]){ A[i][j] = max(A[i - 1][j], A[i][j - 1]); } } } for(int i = 0; i <= str1.length(); i++){ for(int j = 0; j <= str2.length(); j++){ cout << A[i][j]; } cout << endl; } return 0; }
Summary: Whether it is from the table view, or from the point of view matrix rule, the length of the common subsequence that is the largest element in the matrix, and the smallest increase in the minimum number of first elements of a common sequence is the element number of columns and rows.