【问题标题】:Why isn't this factorial finding algorithm O(n!) run-time complexity?为什么这个阶乘查找算法不是 O(n!) 运行时复杂度?
【发布时间】:2020-02-16 04:25:29
【问题描述】:

我通过实现这篇文章中的算法发现了这个问题:Example of O(n!)?

虽然我尝试计算操作数,但算法在计算 4 时循环了 64 次! (即 24)。

我有什么遗漏吗?或者这个算法真的只是具有不是 O(n!) 的运行时复杂度

var operations = 0;

function factorial(n) {
    for (let i = 0; i < n; i++) {
        operations++;
        factorial(n - 1);
    }
}

console.log(factorial(4))
console.log('operations: ', operations) // prints 64 operations

【问题讨论】:

  • O(n!) 不一定意味着 n!本身。这意味着它与 n! 成正比。阶乘增长很快,所以根本不切实际,但您可能想要将 n 与操作与 n 进行对比!看看这是否使这种关系可信。

标签: javascript algorithm time big-o


【解决方案1】:

可能有一个很好的理论分析,但这里是一个经验分析。 我为数字 0 到 12 运行程序并跟踪操作。请注意,这些操作很快就会非常接近前一个条目的 n 倍。以及运算与 n! 的比率!似乎倾向于 e。因此,如果操作的极限是 e(或某个常数)乘以 n!,我们就是 O(n!)。我们不需要 = n!做到这一点。

【讨论】:

  • 考虑到在算法的所有情况下,Big O 往往是一个范围,而不是实际运行时间。
【解决方案2】:

您正在计算每个递归级别的循环操作(即计算除最外层之外的函数调用),而不是计算最内层的函数调用。因此,您得到的计数比您预期的普通阶乘要高得多:

1                         = 1
2 + 2*1                   = 4
3 + 3*2 + 3*2*1           = 15
4 + 4*3 + 4*3*2 + 4*3*2*1 = 64
…

任意n 的扩展可以在https://oeis.org/A007526 中找到。这些仍然受到O(n!)的限制 - 请参阅链接中的封闭公式,例如floor(e*n! - 1) 或 n! * Sum_{k=0..n-1} 1/k!,它们显然由 n! 术语主导。 (计算所有调用会得到https://oeis.org/A000522、n! * Sum_{k=0..n} 1/k!)。

要准确获得阶乘,您只需计算最里面的函数调用:

var operations = 0;

function factorial(n) {
    if (n == 0) operations++;
    for (let i = 0; i < n; i++) {
        factorial(n - 1);
    }
}

console.log(factorial(4))
console.log('operations: ', operations) // prints 64 operations

【讨论】:

  • 这只是计算n == 0 时factorial(n) 的调用次数。这只发生在 for 循环结束时,在完成许多操作之后。
  • @HaysStanford 是的。而且由于那些最里面的调用是最多的,它们支配了运行时的复杂性。我只是想显示这个,因为其中正好有 n!,因为这似乎是您要查找的数字。
【解决方案3】:

阶乘函数应该是:

var operations = 0;

function factorial(n) {
    operation++;
    if (n === 0) return 1;
    return n*factorial(n - 1);
}

console.log(factorial(4))
console.log('operations: ', operations) // prints 24 operations

它是 O(n)。 这个例子是关于 O(n!),这是一个时间复杂度取决于 n!,而不是 n!自己。

【讨论】:

  • 这只是计算阶乘,它的运行时间复杂度不是O(n!)
  • @HaysStanford 我认为如果阶乘函数是 O(n!),你会感到困惑。我编辑了答案。您示例中的函数未命名为阶乘。
猜你喜欢
  • 2021-11-11
  • 1970-01-01
  • 2020-12-16
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多