对于与此类似的代码:
for(int i = 0; i < n; i+=2){
(Code that executes in constant time)
}
我听说这应该是O(N)的运行时间。但由于循环执行n / 2次不应该是O(N / 2)?任何人都可以解释为什么我每次增加2也不会将时间减少2倍?
答案 0 :(得分:4)
如果我们回到Big O符号定义,它会指出f(x) ~ O(g(x))
当且仅当f(x) <= C*g(x)
其中C是常量。常量C可以调整到所需的任何值,在你的情况下,常量是2.当我们引用大O表示法时,不考虑常量和低阶项,因为根据定义,高阶项总是大于它们。
例如,O(N)
始终是常数(C)大于N/c1 + c2
(c1和c2是常量),其中C可以被视为C= c1+c2
另一个例子是,如果我们选择(N^2)+N
,我们可以忽略较低的顺序,并说复杂性为O(N^2)
,因为我们可以将常数C取为2,所以|N^2 + N| <= |N^2 + N^2| or 2|N^2|
我们也可以说N/2 ~ O(N^2)
,但它不是一个紧张的上限。在算法的复杂性中,我们总是努力寻找最严格的界限,并且由于O(N)
是一个更严格的上界,我们通常将它用于单变量单度函数。
答案 1 :(得分:2)
Big O表示法不指定函数运行所需的时间。它仅表示函数的完成时间如何随值的增加/减少而变化。 O(N)表示线性时间增长;同样,O(N / 2)也表示完全相同的线性变化。在编写代码的时间复杂度时,您可以忽略任何系数,因为这些系数不会传达任何其他含义。
答案 2 :(得分:1)
当处理时间复杂度时,数值常数被忽略......原因是如果你看N和1 / 2N的长期运行,常数不会从根本上改变结果。因此,复杂性是简单地减少到O(N)
从技术上讲,它减少了两倍,但减少的幅度不足以考虑整体运行时间,因此运行时间仍为O(N)
只是提供一个图片示例...蓝色和红色线条显示N和N / 2从长远来看基本相同......黄色线条是Nlog(N),相比之下,它对您来说很重要从长远来看,时间远远大于前面提到的两个..
请注意:这个答案仅仅是对大O符号忽略常量的强化,对于特定的定义,请参考上面的@hrv答案
答案 3 :(得分:0)
通常可以将常量考虑在内。 “X”真正占用了处理时间,所以常数并不是那么大,加上Big O时间就像这是一个近似值,实际上并不准确,因为实际时间取决于更多的因素。这与你在for循环中初始化“int i = 0”的原因相同,你没有给出大的时间:
O(N + 1)
因此,O(N)与O(N / 2)
几乎相同尽管其他用户坚持认为它们是相同的,但忽略常量是错误的,因为巨大的常量确实会影响运行时间。所以是的,虽然O(N)可能被认为与O(N / 2)相同,但几乎相同,因为常量会对整体运行时间产生重大影响(考虑O (10 ^ 12N),现在巨大的恒定物质?)
答案 4 :(得分:0)
所以,让我试着解释一下为什么会这样:
你的代码:
for(int i = 0; i < n; i+=2){
(Code that executes in constant time)
}
它实际上取决于底层硬件,但让我们假设每个'Assignment','Comparison','Arithmetic',每个操作都需要单位时间。
所以,
int i = 0
这只执行一次。 Time : 1 unit
i<n
执行n / 2次。 Time : n/2 units
i=i+2
在这里,如果您将看到算术运算和分配操作都执行n / 2次,
Time : n/2 + n/2 = n units
此时我假设for循环中没有任何内容。
运行此循环所需的总时间单位:1 + n / 2 + n = 1 + (3n/2) units of time.
因此,对于小n(实际上是数万个,在底层处理器的计算能力的上下文中),1 + 3n/2 ~~ n.
因为这个小的测试集需要花费几分之一秒。
相反,对于大n(数百万),(1+(3n\2)) < n
,即对于大型测试数据,每个系数肯定具有其重要性,并且可能显着影响相应代码段的总执行时间。
希望它有所帮助。