常规写法
const Fib1 = n => {
console.log(`Fib1(${n})`)
if (n === 0) {
return 0
} else if (n === 1) {
return 1
} else {
return Fib1(n - 1) + Fib1(n - 2)
}
}
console.log(Fib1(5))
// 函数调用顺序
// Fib1(5) Fib1(4) Fib1(3) Fib1(2) Fib1(1) Fib1(0) Fib1(1) Fib1(2) Fib1(1) Fib1(0) Fib1(3) Fib1(2) Fib1(1) Fib1(0) Fib1(1)
可以发现整个过程是二叉树先序遍历的过程。此外,整个过程中多次调用了Fib1(3)
、Fib1(2)
、Fib1(5)
,产生大量冗余的调用。无路什么数据结构最后都是队栈吗?
一行写出斐波那契数列
const Fib1 = n => (n <= 1) ? n : (Fib1(n - 1) + Fib1(n - 2))
改进写法1
将找到斐波那契数列的第n项问题转化为在一个初始项为t0和t1的加法序列(序列中,每一项都是前两项的和)中找到第n项的问题。
求以3和7为初始项的第一个序列中的t6(71)可以转化为求以7和10为初始项的第二个序列中的t5(71)
const Fib2 = n => {
return AdditiveSequence(n, 0, 1)
}
const AdditiveSequence = (n, t0, t1) => {
console.log(`AdditiveSequence(${n},${t0},${t1})`)
if (n === 0) {
return t0
} else if (n === 1) {
return t1
} else {
return AdditiveSequence(n - 1, t1, t0 + t1)
}
}
console.log(Fib2(5))
// AdditiveSequence(5,0,1)
// AdditiveSequence(4,1,1)
// AdditiveSequence(3,1,2)
// AdditiveSequence(2,2,3)
// AdditiveSequence(1,3,5)
改进写法2
求以3和7为初始项的第一个序列中的t6(71)可以转化为求以10和17为初始项的第二个序列中的t4(71)
const Fib3 = n => {
return AdditiveSequence(n, 0, 1)
}
const AdditiveSequence = (n, t0, t1) => {
console.log(`AdditiveSequence(${n},${t0},${t1})`)
if (n === 0) {
return t0
} else if (n === 1) {
return t1
} else {
return AdditiveSequence(n - 2, t0 + t1, t0 + t1 + t1)
}
}
console.log(Fib3(5))
// AdditiveSequence(5,0,1)
// AdditiveSequence(3,1,2)
// AdditiveSequence(1,3,5)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。