没有。考虑到时间复杂度渐近地描述时间 - 我们将较低的时间复杂度吸收到较高的时间复杂度中。
O(n²) 表示k × n² + c,假设c 太低以至于我们不关心它。
这些是恒定的影响,整个事物的一定数量的开销 (c) 以及无论我们的复杂性如何,一定数量的成本。一个n² 算法将击败另一个n² 算法,如果它有一个较低的k,或者如果它们相等,一个较低的c。此外,对于足够低的 n 值,O(n²) 与 O(1) 相同(我们通常不会关心,但每个的 k 可能会有很大不同,而且如果我们每做一次 m 次,那么虽然 O(n²m) 优于 O(m),但如果 n 较低,则不是真正比较的对象)..
无论如何,这是故意的过度简化,因为k 和c 可能并不真正是恒定的,就像恒定一样好。因此,如果某个东西真的是O(n² + log(n)),我们就称它为O(n²),因为当我们有一个n² 需要担心时,谁会关心那个小log(n)?
所以。看着你的情况。我们做外循环,n 次。对于其中的每一个,我们执行内部循环n-1 次。对于每个内部循环,我们进行第一次打印(任何成本差异都与n 无关,因此基本上是恒定的)和测试。测试成功的时间大约有一半,导致第二次打印的成本经常如此。
所以总成本是:
cost of setting up everything +
n × cost of looping +
(n - 1) × cost of loop +
(n × (n - 1)) × cost of print +
(n × (n - 1)) × cost of test +
(n × (n - 1)) / 2 × cost of print.
为上面的常量赋值,我们得到:
k +
n × a +
(n - 1) × b +
(n × (n - 1)) × c +
(n × (n - 1)) × d +
(n × (n - 1)) / 2 × e.
=
k +
n × a +
(n - 1) × b +
(n × (n - 1)) × (c + d + (e / 2))
现在,由于c + d + e / 2 本身是常数,所以可以变成:
n × a + (n - 1) × b + (n × (n - 1)) × c + k
或重新排序,按最高顺序在前:
(n × (n - 1)) × c + (n - 1) × b + n × a + k
如果 n 高到足以让我们该死,那么 n 在比例上如此接近 n - 1,以至于我们不妨认为它们是相同的(时间复杂度的另一个方面是渐近地描述事物,即当 n 接近 ∞因此 n² 和 (n × (n - 1)) 之间的差异接近 0)。因此:
n² × c + n × b + n × a = n² × c + n × (b + a) + k
同样,b + a 本身就是常数,所以它等价于:
n² × k + n × c + a
现在我们做了前面提到的吸收较低时间的订单,谁在乎n × c,没关系吗?如果 n 高到足以让我们完全关心,那么这就是n²。相比之下,我们不妨将总体开销的差异视为噪声,并将其视为:
n² × k + c
或者换句话说,如:
O(n²)
所以是的,你一开始就很努力,if 语句不会影响复杂性。
考虑到这一点,我们可以注意到时间复杂度可能会隐藏我们真正关心的内容。例如,如果我们有一个 O(n²) 算法,如果这种分析发现时间成本为n² × k + n × c,k 为 200µs,c 为 15s,那么直到 n 大于 750000 它实际上是每 n 位成本,而不是每 n² 位。在较低的 n 时,它更接近我们对 O(n) 的期望,而不是 O(n²)。
时间复杂度有用的原因是,如此大的差异是罕见的,而且我们关心时间,因此关心时间复杂度,当 n 变高时(你可以隐藏一些可怕的 O(n !)代码中的怪物,您在蓝月亮中调用过一次,具有三个元素,只是不在乎)。因此,为了实现现实世界的改进,我们理想地希望降低时间复杂度,或者如果未能降低最高级别的常数 k(或者换句话说,如果你可以开始做 n log n 次而不是 n² 次,那么就做,否则减少你正在做 n² 次的事情的成本,而不是你正在做 n 次的其他事情)。
换句话说,它可以帮助我们专注于通常最重要的事情。