Here is the link to algorithm without comments, to see better
function getLastFactor(n) {
var tempArr = [2, 3], max = Math.sqrt(n); /* (1 + 1)
it is despised
*/
for(var i = 5; i < max; i += 2) { /*
(sqrt(n) - 5) ---> ( 5 is despised )
*/
if(n%i) continue; /*
sqrt(n) - 5 operations
PD: Should I add this? or is it already included in the for, in (sqrt(n) - 5 above) ?
*/
if(check(tempArr, i)) continue; // How do I measure this? If I do not have security of the number?
tempArr.push(i); // 1 operation it is despised
}
return tempArr[tempArr.length - 1]; // 1 operation
}
function check(array, i) {
for(var j = 0, l = array.length; j < l; ++j) { // sqrt(n) operations
var cur = array[j]; // 1 operation
if(!(i%cur)) return true; // 1 operation
}
// O(3 * sqrt(n))
我不知道真正加起来的是什么,我已经读过这个并不重要,因为Big O
符号标准化了这一点,消除了次要订单的条款。但是我有许多疑问,比如我在代码中留下的一些疑问,以及:
1)我应该在有条件的情况下计算依赖的操作吗? ,想象一下我有一个条件,如果你评价为真,就会做一个循环来提高n次操作的效率,这应该考虑在内,因为它会发生很大的变化。
2)我认为此代码的效率为O (sqrt (n) * 3)
,这是正确的吗?
这个问题不是另一个问题的重复,我已经通过网络,特别是在这个社区中阅读了很多,而且几乎所有的问题/答案都是基于理论和几乎从未见过的理论和实践的例子。时间。
答案 0 :(得分:1)
首先,当使用big-o表示法时会删除所有常量,因此O (sqrt (n) * 3)
实际上是O (sqrt (n))
。
为了正确分析这段代码的渐近复杂性,我们需要一些数论背景。该算法基本上执行的是确定n
的素因子(仅返回最大值)。程序的主要部分是for
循环,它迭代从5
到sqrt(n)
的所有奇数,因此迭代次数为(sqrt(n) - 5) / 2
,或者用大术语表示, O(sqrt(n))
。
接下来,有一个语句if(n%i) continue;
可以消除所有不是n
除数的数字(无论它们是否为素数)。因此,仅当i
是n
的除数时才执行其余代码。 Asymptotic bound for number of divisors是O(n^{1 / ln(ln(n))})
。
最后,有一个函数check
迭代数组tempArr
,其中包含到目前为止找到的n
的素数除数。一个正整数n
有多少个除数? Asymptotic bound for number of prime divisors是最糟糕的情况(n
被称为primorial number)O(ln(n) / ln(ln(n)))
。
现在让我们总结一切。即使我们假设n
是原始的并且快速找到所有素数除数(因此array.length
具有最大可能值),if(n%i) continue;
之后的代码部分的渐近复杂性为{ {1}}。这并不容易看到,但这比O(n^{1 / ln(ln(n))} * ln(n) / ln(ln(n)))
慢,所以总复杂度为O(sqrt(n))
。