我刚开始学习大O概念。我学到的是,如果函数f小于或等于函数g的另一个常数倍,则f是O(g)。
现在我遇到了一个例子,其中一个大小为“n”的字符串采用“2n”(输入大小的两倍)算法步骤。因此他们说所花费的时间是O(2n),但是他们遵循这个陈述,说As O(2n)= O(n),时间复杂度是O(n)。
我不明白这一点。由于2n总是大于n,我们怎么能忽略2的多个呢?任何小于或等于2n的东西都不一定小于n!
这不是说我们在某种程度上等同n和2n吗?听起来令人困惑。请以最简单的方式澄清,因为我只是这个概念的初学者。 最诚挚的问候:)
答案 0 :(得分:2)
...由于2n总是大于n,我们怎么能忽略2的多个? ... 的
简单地说,随着n
的增长,乘数会失去其重要性。函数的渐近行为描述了n
变大时会发生什么。
或许只考虑O(n)
和O(2n)
会有所帮助,因为它们属于同一类,但要与某些other common classes形成对比。示例:任何O(n^2)
算法都需要比任何O(n)
更长的时间,需要更长时间(在短期内,它们的运行时间甚至可能会被逆转)。假设您有两种算法,一种是线性时间复杂度为100n
,另一种是8n^2
。对于所有n =< 12
,二次算法将更快,但对于所有n > 12
,则更慢。
此属性 - 对于任何已修复的非负c
和d
,您会找到n
,以便cn < dn^2
- 构成一个时间复杂性的一部分。
答案 1 :(得分:2)
Big-O和相关符号旨在捕获算法最固有的算法性能方面,与运行和测量的方式无关。
常数乘数取决于测量单位,秒与微秒相对于指令与循环迭代。即使在相同单位中测量,如果在不同系统上测量,它们也将是不同的。相同的算法可以在一个指令集中采用20n个指令,在另一个指令集上采用30n个指令。一个可能需要0.5n微秒,另一个可能需要10n微秒。
您将在文献中看到的许多基本算法复杂性是在几十年前计算出来的,但在处理器架构的重大变化和性能的更显着变化中仍然有意义。
类似的考虑适用于启动和类似的开销。
如果存在常数N和c,则f(n)
为O(n)
,对于所有n>=N, f(n) <= cn
。对于f(n)= 2n,常数为N=0
和c = 2
。第一个常数N是忽略开销,第二个是c忽略常数乘数。
答案 2 :(得分:1)
正如您在第一段中所提到的,执行算法所需的时间与输入大小的常数倍成正比。您可以将O(n)视为O(C * n),其中C是任何常数乘数。