【问题标题】:Javascript factorial function memoizationJavascript阶乘函数记忆
【发布时间】:2019-04-05 15:26:59
【问题描述】:

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

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

【问题讨论】:

  • 这是一个学习练习吗?如果没有,而您只是在寻找更好的算法,请尝试迭代方法。你会发现它的效率要高得多。

标签: javascript performance factorial memoization


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢我现在明白了!
  • 是否可以将此 factorial() 函数作为回调传递给通用的 memoizer 函数?我已经尝试过了,但由于阶乘函数的递归性质,它似乎不起作用。
【解决方案2】:

正如@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)
其中factorial(6) 基本上是6 * the cached value of factorial(5)

【讨论】:

    猜你喜欢
    • 2012-04-01
    • 2017-05-10
    • 1970-01-01
    • 2013-07-28
    • 2018-12-26
    • 1970-01-01
    • 2011-01-26
    • 2021-01-17
    • 2013-12-04
    相关资源
    最近更新 更多