简体   繁体   English

Javascript 阶乘 function 记忆

[英]Javascript factorial function memoization

I'm trying to use the factorial function with memoization.我正在尝试使用带有记忆的阶乘 function。 I have taken the max value from the object to reduce the number of recursive calls made.我从 object 中获取了最大值,以减少递归调用的次数。 But the problem is the first call is I don't know whether this is optimized or not since the first call is pretty expensive.但问题是第一次调用我不知道这是否经过优化,因为第一次调用非常昂贵。 Any insights on this will be great.对此的任何见解都会很棒。

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];
}

You don't buy much from memoizing this since you only use each value once.你不会因为记住这个而买太多东西,因为你只使用每个值一次。 After you've called the function you do have the cache for a second call, but we often think of memoizing as something that happens in a cache that only exists during the function.在您调用函数之后,您确实拥有第二次调用的缓存,但我们通常认为记忆是发生在仅在函数期间存在的缓存中的事情。 For something like that, calculating Fibonacci numbers is a classic example where memoizing is a huge improvement over the naive recursive function.对于这样的事情,计算斐波那契数是一个经典的例子,其中记忆是对朴素递归函数的巨大改进。

Having said that, in your function it's not clear why you are using an object for your cache and then searching it.话虽如此,在您的函数中,尚不清楚您为什么将对象用于缓存然后进行搜索。 You can just use an array where the indexes will be the number you're looking for calculate.您可以只使用一个数组,其中索引将是您要计算的数字。 You don't need to search it, just start with the number and recursively call the next lower one.您不需要搜索它,只需从数字开始并递归调用下一个较低的数字即可。 If there's a cache it, it will return.如果有缓存,它会返回。 For example:例如:

 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))

As @mark-meyer mentioned in this thread, there is no advantage coming from memoizing the results since each value will be calculated only one time during computation.正如@mark-meyer 在此线程中提到的那样,记住结果没有任何好处,因为在计算过程中每个值只会计算一次。 The solution Mark offered is great for reusing the function in a later time by re-calling factorials with same or different values. Mark 提供的解决方案非常适合稍后通过重新调用具有相同或不同值的阶乘来重用该函数。 In that case, you can speed up the process and reduce the time complexity by reusing existing results.在这种情况下,您可以通过重用现有结果来加快流程并降低时间复杂度。

Here is how it can look like in a closure:这是它在闭包中的样子:

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);
  }
}

Then, you can use it like so:然后,您可以像这样使用它:

const factorial = factorialFn();

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


At the first call, it will calculate factorial(5) and save it in cache for future reference. 在第一次调用时,它会计算factorial(5)并将其保存在缓存中以备将来参考。

At the second call, factorial(7) will execute 7 * factorial(6) , 在第二次调用时, factorial(7)将执行7 * factorial(6)
which factorial(6) is basically 6 * the cached value of factorial(5) 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