@@ -69,7 +69,83 @@ const FibonacciDpWithoutRecursion = (number) => {
69
69
return table
70
70
}
71
71
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
+
72
147
export { FibonacciDpWithoutRecursion }
73
148
export { FibonacciIterative }
74
149
export { FibonacciRecursive }
75
150
export { FibonacciRecursiveDP }
151
+ export { FibonacciMatrixExpo }
0 commit comments