繁体   English   中英

Javascript 阶乘 function 记忆

[英]Javascript factorial function memoization

我正在尝试使用带有记忆的阶乘 function。 我从 object 中获取了最大值,以减少递归调用的次数。 但问题是第一次调用我不知道这是否经过优化,因为第一次调用非常昂贵。 对此的任何见解都会很棒。

let cache = {0: 1};
function factMemoize(key) {
    if (!cache[key]) {
        let maxVal = Object.keys(cache).reduce(function (a, b) {
            return Math.max(a, b);
        });
        console.log(maxVal);
        while (key >= maxVal) {
            cache[key] = key * factMemoize(key - 1);
            maxVal++;
        }
    }
    return cache[key];
}

你不会因为记住这个而买太多东西,因为你只使用每个值一次。 在您调用函数之后,您确实拥有第二次调用的缓存,但我们通常认为记忆是发生在仅在函数期间存在的缓存中的事情。 对于这样的事情,计算斐波那契数是一个经典的例子,其中记忆是对朴素递归函数的巨大改进。

话虽如此,在您的函数中,尚不清楚您为什么将对象用于缓存然后进行搜索。 您可以只使用一个数组,其中索引将是您要计算的数字。 您不需要搜索它,只需从数字开始并递归调用下一个较低的数字即可。 如果有缓存,它会返回。 例如:

 let cache = [1]; function factMemoize(key) { if (!cache[key]) { cache[key] = key * factMemoize(key - 1) } else { // just to demo cache: console.log("cache hit:", key) } return cache[key] } // only hits cache at the end console.log("6! = ", factMemoize(6)) // second call benefits from cache: console.log("8! = ", factMemoize(8))

正如@mark-meyer 在此线程中提到的那样,记住结果没有任何好处,因为在计算过程中每个值只会计算一次。 Mark 提供的解决方案非常适合稍后通过重新调用具有相同或不同值的阶乘来重用该函数。 在这种情况下,您可以通过重用现有结果来加快流程并降低时间复杂度。

这是它在闭包中的样子:

function factorialFn() {
  const cache = [];

  return function _factorial() {
    if (n < 2) {
      return 1;
    }
    if (cache[n]) {
      return cache[n];
    }
    return cache[n] = n * _factorial(n - 1);
  }
}

然后,您可以像这样使用它:

const factorial = factorialFn();

factorial(5); // 120
factorial(7); // 5040


在第一次调用时,它会计算factorial(5)并将其保存在缓存中以备将来参考。

在第二次调用时, factorial(7)将执行7 * factorial(6)
which factorial(6)基本上是6 * the cached value of factorial(5)

function factorial(n, cache = {}) {
    if (n < 2) return 1;
    if (n in cache) return cache[n];
    return cache[n] = n * factorial(n - 1, cache);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM