forked from TheAlgorithms/JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Fibonacci.js
156 lines (131 loc) · 3.77 KB
/
Fibonacci.js
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
const list = []
const FibonacciIterative = (nth) => {
const sequence = []
if (nth >= 1) sequence.push(1)
if (nth >= 2) sequence.push(1)
for (let i = 2; i < nth; i++) {
sequence.push(sequence[i - 1] + sequence[i - 2])
}
return sequence
}
const FibonacciRecursive = (number) => {
return (() => {
switch (list.length) {
case 0:
list.push(1)
return FibonacciRecursive(number)
case 1:
list.push(1)
return FibonacciRecursive(number)
case number:
return list
default:
list.push(list[list.length - 1] + list[list.length - 2])
return FibonacciRecursive(number)
}
})()
}
const dict = new Map()
const FibonacciRecursiveDP = (stairs) => {
if (stairs <= 0) return 0
if (stairs === 1) return 1
// Memoize stair count
if (dict.has(stairs)) return dict.get(stairs)
const res =
FibonacciRecursiveDP(stairs - 1) + FibonacciRecursiveDP(stairs - 2)
dict.set(stairs, res)
return res
}
// Algorithms
// Calculates Fibonacci(n) such that Fibonacci(n) = Fibonacci(n - 1) + Fibonacci(n - 2)
// Fibonacci(0) = Fibonacci(1) = 1
// Uses a bottom up dynamic programming approach
// Solve each sub-problem once, using results of previous sub-problems
// which are n-1 and n-2 for Fibonacci numbers
// Although this algorithm is linear in space and time as a function
// of the input value n, it is exponential in the size of n as
// a function of the number of input bits
// @Satzyakiz
const FibonacciDpWithoutRecursion = (number) => {
const table = []
table.push(1)
table.push(1)
for (let i = 2; i < number; ++i) {
table.push(table[i - 1] + table[i - 2])
}
return table
}
// Using Matrix exponentiation to find n-th fibonacci in O(log n) time
const copyMatrix = (A) => {
return A.map(row => row.map(cell => cell))
}
const Identity = (size) => {
const I = Array(size).fill(null).map(() => Array(size).fill())
return I.map((row, rowIdx) => row.map((_col, colIdx) => {
return rowIdx === colIdx ? 1 : 0
}))
}
// A of size (l x m) and B of size (m x n)
// product C will be of size (l x n)
const matrixMultiply = (A, B) => {
A = copyMatrix(A)
B = copyMatrix(B)
const l = A.length
const m = B.length
const n = B[0].length // Assuming non-empty matrices
const C = Array(l).fill(null).map(() => Array(n).fill())
for (let i = 0; i < l; i++) {
for (let j = 0; j < n; j++) {
C[i][j] = 0
for (let k = 0; k < m; k++) {
C[i][j] += A[i][k] * B[k][j]
}
}
}
return C
}
/**
* Computes A raised to the power n i.e. pow(A, n) where A is a square matrix
* @param {*} A the square matrix
* @param {*} n the exponent
*/
// A is a square matrix
const matrixExpo = (A, n) => {
A = copyMatrix(A)
// Just like Binary exponentiation mentioned in ./BinaryExponentiationIterative.js
let result = Identity(A.length) // Identity matrix
while (n > 0) {
if (n % 2 !== 0) result = matrixMultiply(result, A)
n = Math.floor(n / 2)
if (n > 0) A = matrixMultiply(A, A)
}
return result
}
const FibonacciMatrixExpo = (n) => {
// F(0) = 0, F(1) = 1
// F(n) = F(n-1) + F(n-2)
// Consider below matrix multiplication:
// | F(n) | |1 1| |F(n-1)|
// | | = | | * | |
// |F(n-1)| |1 0| |F(n-2)|
// Let's rewrite it as F(n, n-1) = A * F(n-1, n-2)
// or F(n, n-1) = A * A * F(n-2, n-3)
// or F(n, n-1) = pow(A, n-1) * F(1, 0)
if (n === 0) return 0
const A = [
[1, 1],
[1, 0]
]
const poweredA = matrixExpo(A, n - 1) // A raised to the power n-1
let F = [
[1],
[0]
]
F = matrixMultiply(poweredA, F)
return F[0][0]
}
export { FibonacciDpWithoutRecursion }
export { FibonacciIterative }
export { FibonacciRecursive }
export { FibonacciRecursiveDP }
export { FibonacciMatrixExpo }