@@ -69,7 +69,83 @@ const FibonacciDpWithoutRecursion = (number) => {
6969 return table
7070}
7171
72+ // Using Matrix exponentiation to find n-th fibonacci in O(log n) time
73+
74+ const copyMatrix = ( A ) => {
75+ return A . map ( row => row . map ( cell => cell ) ) ;
76+ }
77+
78+ const Identity = ( size ) => {
79+ const I = Array ( size ) . fill ( null ) . map ( ( ) => Array ( size ) . fill ( ) ) ;
80+ return I . map ( ( row , rowIdx ) => row . map ( ( _col , colIdx ) => {
81+ return rowIdx === colIdx ? 1 : 0
82+ } ) )
83+ }
84+
85+ // A of size (l x m) and B of size (m x n)
86+ // product C will be of size (l x n)
87+ const matrixMultiply = ( A , B ) => {
88+ A = copyMatrix ( A )
89+ B = copyMatrix ( B )
90+ const l = A . length
91+ const m = B . length
92+ const n = B [ 0 ] . length // Assuming non-empty matrices
93+ const C = Array ( l ) . fill ( null ) . map ( ( ) => Array ( n ) . fill ( ) ) ;
94+ for ( let i = 0 ; i < l ; i ++ ) {
95+ for ( let j = 0 ; j < n ; j ++ ) {
96+ C [ i ] [ j ] = 0
97+ for ( let k = 0 ; k < m ; k ++ ) {
98+ C [ i ] [ j ] += A [ i ] [ k ] * B [ k ] [ j ]
99+ }
100+ }
101+ }
102+ return C
103+ }
104+
105+ // A is a square matrix
106+ const matrixExpo = ( A , n ) => {
107+ A = copyMatrix ( A )
108+ if ( n == 0 ) return Identity ( A . length ) // Identity matrix
109+ if ( n == 1 ) return A
110+
111+ // Just like Binary exponentiation mentioned in ./BinaryExponentiationIterative.js
112+ let result = Identity ( A . length )
113+ while ( n > 0 ) {
114+ if ( n % 2 !== 0 ) result = matrixMultiply ( result , A )
115+ n = Math . floor ( n / 2 )
116+ if ( n > 0 ) A = matrixMultiply ( A , A )
117+ }
118+ return result
119+ }
120+
121+ const FibonacciMatrixExpo = ( n ) => {
122+ // F(0) = 0, F(1) = 1
123+ // F(n) = F(n-1) + F(n-2)
124+ // Consider below matrix multiplication:
125+
126+ // | F(n) | |1 1| |F(n-1)|
127+ // | | = | | * | |
128+ // |F(n-1)| |1 0| |F(n-2)|
129+
130+ // F(n, n-1) = pow(A, n-1) * F(1, 0)
131+
132+ if ( n === 0 ) return 0 ;
133+
134+ const A = [
135+ [ 1 , 1 ] ,
136+ [ 1 , 0 ]
137+ ]
138+ const poweredA = matrixExpo ( A , n - 1 ) // A raise to the power n
139+ let F = [
140+ [ 1 ] ,
141+ [ 0 ]
142+ ]
143+ F = matrixMultiply ( poweredA , F )
144+ return F [ 0 ] [ 0 ]
145+ }
146+
72147export { FibonacciDpWithoutRecursion }
73148export { FibonacciIterative }
74149export { FibonacciRecursive }
75150export { FibonacciRecursiveDP }
151+ export { FibonacciMatrixExpo }
0 commit comments