Http://zhedahht.blog.163.com/blog/static/25411174200722991933440/
Question: Define the series of Fibonacci:
/0 n = 0
F (n) = 1 n = 1
\ F (n-1) + f (n-2) n = 2
Enter N and use the fastest method to obtain the nth item of the series.
Analysis: when we talk about recursive functions in many C language textbooks, we will use Fibonacci as an example. Therefore, many programmers are very familiar with the recursive solution to this question. When they see the question, they can write the following code for Recursive solution.
///////////////////////////////////////////////////////////////////////// Calculate the nth item of Fibonacci Series recursively///////////////////////////////////////////////////////////////////////long long Fibonacci_Solution1(unsigned int n){ int result[2] = {0, 1}; if(n < 2) return result[n]; return Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2);}
However, the textbook repeatedly uses this question to explain recursive functions, but it does not mean that recursive solutions are the most suitable for this question. We use solving F (10) as an example to analyze the recursive solution process. F (10) and F (9) and F (8) are required ). Similarly, if F (9) is required, F (8) and F (7)… must be obtained first )...... We use a tree structure to represent this dependency.
F (10)
/\
F (9) f (8)
/\/\
F (8) f (7) f (7) f (6)
/\/\
F (7) f (6) f (6) f (5)
It is not difficult to find that many nodes in this tree will be repeated, and the number of duplicate knots will increase sharply with the increase of N. This means that the amount of computing will increase sharply with the increase of N. In fact, the time complexity calculated using recursive methods increases exponentially by N. You can try Fibonacci's 100th items to find out how slow the recursion will be. After running on my machine for more than an hour, no result is returned.
In fact, the improvement method is not complicated. The above method is slow because there are too many repeated computations. You just need to avoid repeated computations. For example, we can save the intermediate items of the obtained series. If we need to calculate them next time, we will first look for them. If we have already calculated them, we don't need to calculate them again.
The simpler method is to calculate from the bottom up. First, F (2) is calculated based on F (0) and F (1) calculate F (3 )...... So far, we can calculate the nth item. It is easy to understand that the time complexity of this approach is O (n ).
///////////////////////////////////////////////////////////////////////// Calculate the nth item of Fibonacci Series iteratively///////////////////////////////////////////////////////////////////////long long Fibonacci_Solution2(unsigned n){ int result[2] = {0, 1}; if(n < 2) return result[n]; long long fibNMinusOne = 1; long long fibNMinusTwo = 0; long long fibN = 0; for(unsigned int i = 2; i <= n; ++ i) { fibN = fibNMinusOne + fibNMinusTwo; fibNMinusTwo = fibNMinusOne; fibNMinusOne = fibN; } return fibN;}
This is not the fastest way. The following describes a method in which the time complexity is O (logn. Before introducing this method, we first introduce a mathematical formula:
{F (N), F (n-1), F (n-1), F (n-2) }={ 1, 1}N-1
(Note: {f (n + 1), F (N), F (N), F (n-1)} represents a matrix. In the matrix, the first column in the first row is F (n + 1), the second column in the first row is F (n), and the first column in the second row is F (n ), the second row and the second column are f (n-1 ).)
With this formula, F (n) is required. We only need to obtain the n-1 power of the matrix {1, 1,}, because the matrix is {1, 1, F (n) is the first column in the first row of the result given by the n-1 power of 1, 0 ). This mathematical formula is easily proved by mathematical induction. If you are interested, you may wish to prove it yourself.
The current problem is to evaluate the multiplication of the matrix {1, 1, 1, 0. If it is simple to start a loop from 0, the Npower will require N operations, not faster than the previous method. However, we can consider the following properties:
/N/2 *When n/2 N is an even number
AN =
\ (N-1)/2 *(N-1)/2 when n is an odd number
To obtain the power of N, we first obtain the power of n/2, and then square the result of n/2. If we look at the question of the power of Npower as a big problem, we can think of n/2 as a small problem. This idea of breaking down a big problem into one or more small problems is called divide and conquer law. In this way, only logn operations are required to calculate the nth power.
To implement this method, you must first define a 2 × 2 matrix and define the multiplication and multiplication operations of the matrix. After these operations are defined, the rest will become very simple. The complete implementation code is as follows.
#include <cassert>///////////////////////////////////////////////////////////////////////// A 2 by 2 matrix///////////////////////////////////////////////////////////////////////struct Matrix2By2{ Matrix2By2 ( long long m00 = 0, long long m01 = 0, long long m10 = 0, long long m11 = 0 ) :m_00(m00), m_01(m01), m_10(m10), m_11(m11) { } long long m_00; long long m_01; long long m_10; long long m_11;};///////////////////////////////////////////////////////////////////////// Multiply two matrices// Input: matrix1 - the first matrix// matrix2 - the second matrix//Output: the production of two matrices///////////////////////////////////////////////////////////////////////Matrix2By2 MatrixMultiply( const Matrix2By2& matrix1, const Matrix2By2& matrix2){ return Matrix2By2( matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10, matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11, matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10, matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11);}///////////////////////////////////////////////////////////////////////// The nth power of matrix // 1 1// 1 0///////////////////////////////////////////////////////////////////////Matrix2By2 MatrixPower(unsigned int n){ assert(n > 0); Matrix2By2 matrix; if(n == 1) { matrix = Matrix2By2(1, 1, 1, 0); } else if(n % 2 == 0) { matrix = MatrixPower(n / 2); matrix = MatrixMultiply(matrix, matrix); } else if(n % 2 == 1) { matrix = MatrixPower((n - 1) / 2); matrix = MatrixMultiply(matrix, matrix); matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0)); } return matrix;}///////////////////////////////////////////////////////////////////////// Calculate the nth item of Fibonacci Series using devide and conquer///////////////////////////////////////////////////////////////////////long long Fibonacci_Solution3(unsigned int n){ int result[2] = {0, 1}; if(n < 2) return result[n]; Matrix2By2 PowerNMinus2 = MatrixPower(n - 1); return PowerNMinus2.m_00;}