[英]Why isn't this factorial finding algorithm O(n!) run-time complexity?
I discovered this issue by implemented the algorithm from this post: Example of O(n!)?我通过实现这篇文章中的算法发现了这个问题: O(n!) 的例子?
I tried counting the operations though, and the algorithm loops 64 times when calculating 4!不过,我尝试对操作进行计数,计算 4 时,算法循环了 64 次! (which is 24).
(这是 24)。
Is there something I'm missing?有什么我想念的吗? Or does this algorithm really just have a run-time complexity that is not O(n!)
或者这个算法真的只是有一个不是 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
There is probably a good theoretical analysis, but here is an empirical one.可能有一个很好的理论分析,但这里是一个经验分析。
I ran the program for numbers 0 to 12 and tracked operations.
我运行了数字 0 到 12 的程序并跟踪了操作。 Notice that very quickly the operations tend to be really close to n times the previous entry.
请注意,操作很快就会非常接近前一个条目的 n 倍。 And the ratio of operations to n!
以及操作数与 n 的比率! appears to tend to e.
似乎倾向于 e。 Thus, if the limit of operations is e (or some constant) times n!, we are O(n!).
因此,如果操作的限制是 e(或某个常数)乘以 n!,我们是 O(n!)。 We need not = n!
我们不需要= n! to make that so.
做到这一点。
You're counting loop operations on every recursion level (ie counting function calls except for the outermost one), instead of counting the innermost function calls.您在每个递归级别计算循环操作(即计算除最外层的函数调用),而不是计算最内层的函数调用。 Therefore you're getting a much higher count than the plain factorial you were expecting:
因此,您得到的计数比您期望的普通阶乘要高得多:
1 = 1
2 + 2*1 = 4
3 + 3*2 + 3*2*1 = 15
4 + 4*3 + 4*3*2 + 4*3*2*1 = 64
…
The expansions for arbitrary n
can be found in https://oeis.org/A007526 .任意
n
的扩展可以在https://oeis.org/A007526 中找到。 These are still limited by O(n!)
though - see the closed formulas in the link, eg floor(e*n! - 1)
or n! * Sum_{k=0..n-1} 1/k!
这些仍然受到
O(n!)
限制- 请参阅链接中的封闭公式,例如floor(e*n! - 1)
或n! * Sum_{k=0..n-1} 1/k!
n! * Sum_{k=0..n-1} 1/k!
, which are clearly dominated by the n!
,这显然是由
n!
term.学期。 (Counting all invocations gives you https://oeis.org/A000522 ,
n! * Sum_{k=0..n} 1/k!
). (计算所有调用给你https://oeis.org/A000522 ,
n! * Sum_{k=0..n} 1/k!
)。
To get exactly a factorial, you'd need to count only the innermost function calls:要获得精确的阶乘,您只需要计算最内部的函数调用:
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
The factorial function should be:阶乘函数应该是:
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
And it's O(n).它是 O(n)。 The example is about O(n!), which is a time complexity depend on n!, not n!
这个例子是关于 O(n!),它的时间复杂度取决于 n!,而不是 n! itself.
本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.