Javascript 如何解释缓存斐波那契算法的复杂性
我试图正确解释缓存的斐波那契算法的复杂性。下面是代码():Javascript 如何解释缓存斐波那契算法的复杂性,javascript,algorithm,memoization,Javascript,Algorithm,Memoization,我试图正确解释缓存的斐波那契算法的复杂性。下面是代码(): 函数allFib(n){ var memo=[]; 对于(变量i=0;i
函数allFib(n){
var memo=[];
对于(变量i=0;i
该解决方案取自“破解编码面试”,并适用于javascript。
这是一个“不太好”的函数调用树
我是这样想的:“最左边的分支(粗体的分支)是进行求值的地方”,它肯定是第一次传递给allFib函数的数字。因此复杂性为O(n)。右边的所有内容都将从缓存中获取,不需要额外的函数调用”。是否正确?以及如何将其连接到树“理论”中。在这种情况下,树的深度和高度是4,但不是5(接近n,但不是它).我希望答案不是直观的,而是更可靠的。首先,检查是否为负值
n
,然后将值移到零
然后检查是否缓存了某个值,获取该值。如果未缓存,则将该值分配给缓存并返回结果
对于n===0
或n==1
的特殊情况,分配n
函数斐波那契(数字){
函数f(n){
在缓存中返回n?
缓存[n]:
缓存[n]=n==0 | | n==1?n:f(n-1)+f(n-2);
}
var缓存=[];
返回f(数字);
}
console.log(fibonacci(15));
console.log(fibonacci(5));
这里有一个真正使用缓存的函数:
函数Fibonacci(){
var memo=[0,1];
this.callCount=0;
this.calc=函数(n){
这个是.callCount++;
返回n当涉及缓存时,f(k)被计算多少次(对于任何k)?
memo[n]
未使用!是的,memo未使用首先检查memo中是否存在值if not然后只计算fib()并分配给memo。if(memo[n]){return memo[n]}else{memo[n]=fib(n-1,memo)+fib(n-2,memo);return memo[n];}嗯,O(n)
是计算未缓存/新值的复杂度。访问缓存值的复杂度是O(1)
,因此此算法的最终复杂度必须介于O(1)
和O(n)
之间,具体取决于n
和缓存的状态。是的,这可能是您的“问题”此时,缓存被提供给函数,因此您永远不知道该缓存中有多少值;在allFib
的情况下,您总是从一个新的(空)缓存开始。但是您可以重用缓存,然后对allFib()的第二次调用将“计算”从缓存中取出相同的5个值。因此,在只进行5次计算的情况下,总共计算了10个值,其余的值从缓存中取出。通常我会将缓存烘焙到fib函数中,避免这种不确定。我会通过预计算cache=[0,1]来处理特殊情况
然后您可以从函数中删除该部分n==0 | | n==1?n:
。
function allFib(n) {
var memo = [];
for (var i = 0; i < n; i++) {
console.log(i + ":" + fib(i, memo))
}
}
function fib(n, memo) {
if (n < 0) return 0;
else if (n === 1) return 1;
else if (memo[n]) return memo[n];
memo[n] = fib(n - 1, memo) + fib(n - 2, memo);
return memo[n];
}
allFib(5);