我们有4种算法,所有这些算法的复杂程度取决于m
和n
,例如:
Alg1:O(m+n)
Alg2:O(mlogm + nlogn)
Alg3:O(mlogn + nlogm)
Alg4:O(m+n!)
(哎哟,这个很糟糕,但无论如何)
现在,如果我们现在n>m
,我们该如何处理?我的第一个想法是:大O符号“丢弃”常数和较小的变量,因为无论什么时候,但迟早“更大的术语”将压倒所有其他的,使它们与计算成本无关。
那么,我们可以将Alg1重写为O(n)
,还是将Alg2重写为O(mlogm)
?如果是这样,那么其他人呢?
答案 0 :(得分:6)
是的,如果您知道n> m的情况总是如此,那么您可以重写它。在形式上,看看这个
如果我们知道n> m(总是)那么它就是
<O(m+n) < O(n+n)
O(2n) = O(n)
O(mlogm + nlogn) < O(nlogn + nlogn) = O(2nlogn) = O(nlogn)
(我们并不关心2)
我们也可以对其他算法说同样的事情
O((2n)!)
我认为你可以看到其他人的去向。但如果你不知道n>那你就不能说上面了。
编辑:正如@rici很好地指出的那样,你也需要小心,因为它总是依赖于给定的功能。 (请注意,O(n!)
无法简化为(2n)! = (2n) * (2n-1) * (2n-2)... < 2(n) * 2(n-1) * 2(n-2) ...
)
通过一些游戏,你可以看到这是不是真的
(2n)! = (2n) * (2n-1) * (2n-2)... < 2^n * n!
=&GT; O((2n)!)
(在组合所有2个系数之后)
因此,我们可以看到O(2^n * n!)
更像minimum = avg - 2 * std
maximum = avg + 2 * std
height = (2/8)*(maximum-minimum)
fig = plt.figure(figsize=(8, 2))
ax = fig.add_axes([minimum, 0, maximum, height])
ax.set_xlim((minimum, maximum))
ax.set_ylim((0,height))
以获得更准确的计算,您可以在此处查看此主题Are the two complexities O((2n + 1)!) and O(n!) equal?
答案 1 :(得分:3)
考虑找到数组中k个最大元素的问题。有一个很好的O(n log k)时间算法,只使用O(k)空间来解决这个问题,该空间通过维持最多k个元素的二进制堆来工作。在这种情况下,由于k保证不大于n,我们可以将这些边界重写为O(n log n)时间与O(n)内存,但最终不太精确。运行时和内存使用对k的直接依赖性表明,该算法需要更多时间,并且随着k的变化使用更多内存。
同样,考虑许多标准图算法,如Dijkstra算法。如果使用Fibonacci堆实现Dijkstra算法,则运行时计算出O(m + n log n),其中m是节点数,n是边数。如果你假设你的输入图是连接的,那么运行时也恰好是O(m + m log m),但是它的界限不如我们的那个。
另一方面,如果使用二进制堆实现Dijkstra算法,则运行时可以达到O(m log n + n log n)。在这种情况下(再次假设图形已连接),m log n项严格地支配n log n项,因此将其重写为O(m log n)并不会失去任何精度。
一般来说,您希望在记录一段代码的运行时和内存使用过程中提供最精确的界限。如果你有一个明确严格控制另一个的多个术语,你可以安全地丢弃那些较低的术语。但除此之外,我不建议丢弃其中一个变量,因为这会在你给出的约束中失去精确度。