mirror of
https://github.com/TheAlgorithms/JavaScript.git
synced 2025-07-18 17:49:40 +08:00
157 lines
3.8 KiB
JavaScript
157 lines
3.8 KiB
JavaScript
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 (var 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 }
|