zoukankan      html  css  js  c++  java
  • Fibonacci 数列第 N项 O(logN)算法

    时间复杂度为O( log n )的方法:

     该算法使用矩阵乘法操作,使得算法时间复杂度为 O(logN)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    long long Fibonacci( unsigned n )   
    {   
          int result[2] = {0, 1};   
          if(n < 2)   
                return result[n];   
     
          long long   fibOne = 0;   
          long long   fibTwo = 1;   
          long long   fibThree ;   
         
          for(unsigned int i = 2; i <= n; ++ i)   
           {   
                 fibThree = fibOne + fibTwo;   
          fibOne = fibTwo ;   
                 fibNTwo = fibThree;   
            }   
            return fibThree;   
    }
      
     
    /*
    下面介绍一种时间复杂度是O(logn)的方法:
     
    对于斐波那契数列1,1,2,3,5,8,13…….有如下定义:
     
    F( n ) = F( n-1 ) + F( n-2 )
    F( 1 ) = 1
    F( 2 ) = 1
     
    矩阵形式:
     
    [ F( n+1 ) ,  F( n ) ] = [ F( n ) , F( n-1 ) ] * Q  其中 [ F( n+1 ) ,  F( n ) ]为行向量,Q = { [ 1, 1 ]; [ 1, 0 ] }为矩阵
     
    则 [ F( n+1 ) , F( n ) ]=[ 1 , 0 ] * Qn , 
    */struct Matrix    
    {          
           long long m_00, m_01, m_10, m_11;   
       Matrix ( 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 )     
           {    
           }    
    };
      
     
    Matrix MatrixMultiply (  const Matrix & m1, const Matrix & m2    )    
    {  
      long long m00 = m1.m_00 * m2.m_00 + m1.m_01 * m2.m_10;
      long long m01 = m1.m_00 * m2.m_01 + m1.m_01 * m2.m_11; 
      long long m10 = m1.m_10 * m2.m_00 + m1.m_11 * m2.m_10    
      long long m11 = m1.m_10 * m2.m_01 + m1.m_11 * m2.m_11; 
          return Matrix ( m00,  m01,  m10, m11 );    
    }
     
    Matrix MatrixPower( unsigned int n )    
    {    
           assert(n > 0);    
           Matrix m;    
           if( n == 1)    
           {    
                 m = Matrix(1, 1, 1, 0);    
           }    
          else if(n % 2 == 0)    
           {    
                 m = MatrixPower( n / 2 );    
                 m = MatrixMultiply( matrix, matrix );    
           }    
          else if( n % 2 == 1 )    
           {    
                 m = MatrixPower( (n - 1) / 2 );    
                 m = MatrixMultiply( m, m );    
                 m = MatrixMultiply( m, Matrix( 1, 1, 1, 0 ) );    
           }     
          return m;    
    }  
    long long Fibonacci( unsigned int n )
    {
          int result[2] = { 0, 1 };
          if( n < 2 )
                return result[ n ];
     
          Matrix Q = MatrixPower( n - 1 );  //注意:按定义式应该用[ 1, 0 ]*Q, 或者等价于{ [ 1 , 0 ]; [ 0, 0 ] }*Q, 但是因为显然结果相同,所以略去这一步。return Q.m_00;
    }


    牛客网答案
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    class Solution {
    public:
        int Fibonacci(int n) {
            int result[2]={0,1};
            if(n<2)return result[n];
            Matrix m;
            return m.Power(n-1).a00;
        }
        class Matrix{
              
        public:
            long int a00;
            long int a01;
            long int a10;
            long int a11;
            Matrix (long int a,long int b,long int c,long int d){
                a00=a;
                a01=b;
                a10=c;
                a11=d;
            }
            Matrix (){
                a00=1;a01=1;a10=1;a11=0;
            }
            Matrix operator * (Matrix & m2){
                long int b00 = a00 * m2.a00 + a01 * m2.a10;
                long int b01 = a00 * m2.a01 + a01 * m2.a11;
                long int b10 = a10 * m2.a00 + a11 * m2.a10;   
                long int b11 = a10 * m2.a01 + a11 * m2.a11;
                return Matrix(b00,b01,b10,b11);
            }
            Matrix Power( unsigned int n )   
            {   
                   Matrix m;   
                   if( n == 1)   
                   {   
                         m = Matrix(1, 1, 1, 0);   
                   }   
                  else if(n % 2 == 0)   
                   {   
                         m = Power( n / 2 );   
                         m = m*m;   
                   }   
                  else if( n % 2 == 1 )   
                   {   
                         m = Power( (n - 1) / 2 );   
                         m = m*m; 
                         Matrix tmp;
                         m = m*tmp ;   
                   }    
                  return m;   
            
           };     
    };




  • 相关阅读:
    类和对象系列教材 (一)- 什么是Java中的引用?
    类和对象系列教材 (一)- 什么是Java中的引用?
    数组系列教材 (七)- java.util.Arrays类常用方法
    数组系列教材 (七)- java.util.Arrays类常用方法
    数组系列教材 (七)- java.util.Arrays类常用方法
    数组系列教材 (六)- Java 如何使用二维数组
    数组系列教材 (六)- Java 如何使用二维数组
    [LeetCode] 938. Range Sum of BST
    [LeetCode] 13. Roman to Integer
    [LeetCode] 12. Integer to Roman
  • 原文地址:https://www.cnblogs.com/zhxshseu/p/5284962.html
Copyright © 2011-2022 走看看