为什么O(1)!= O(log(n))?对于n = [整数,长整数......]

时间:2010-12-19 16:06:59

标签: algorithm complexity-theory big-o

例如,假设n = Integer.MAX_VALUE或2 ^ 123则O(log(n))= 32和123因此是一个小整数。不是O(1)?

有什么区别?我认为,原因是O(1)是常数但O(log(n))不是。还有其他想法吗?

8 个答案:

答案 0 :(得分:11)

如果n超出限定范围,则涉及n的复杂性类别毫无意义。没有“在2 ^ 123接近无限的限度内”这样的东西,除了“五角形近似于圆形的旧笑话,足够大的5的值”。

通常,在分析代码的复杂性时,我们假设输入大小不受机器资源限制的限制,即使它是。这确实导致log n周围发生一些奇怪的事情,因为如果n必须适合固定大小的int类型,那么log n有一个相当小的界限,所以界限更有可能是有用/相关的。

所以有时候,我们正在分析一个稍微理想化的算法版本,因为写的实际代码不能接受任意大的输入。

例如,你的平均快速排序在最坏的情况下正式使用Theta(log n)堆栈,显然是这样的相当常见的实现,在分区的“小”方面调用recurses并且在“大”上循环recurses “一面。但是在32位机器上你可以安排使用一个大约240字节的固定大小的数组来存储“待办事项列表”,这可能比你根据正式有O的算法编写的其他函数要少。 (1)堆栈使用。道德是实现!=算法,复杂性并没有告诉你关于小数字的任何信息,任何特定的数字都是“小”。

如果你想考虑边界,你可以 说,例如,你对数组进行排序的代码是O(1)运行时间,因为数组必须小于适合您PC的地址空间,因此对其进行排序的时间是有限的。但是,如果您这样做,您的CS任务将失败,并且您不会向任何人提供任何有用的信息: - )

答案 1 :(得分:4)

显然,如果您知道输入将始终具有固定数量的元素,则算法将始终以恒定时间运行。 Big-O表示法用于表示更糟糕的运行时间,它描述了元素数量无限大时的限制。

答案 2 :(得分:4)

区别在于n不固定。 Big-O表示法背后的想法是了解输入的大小如何影响运行时间(或内存使用)。因此,如果算法总是花费相同的时间,无论n = 1还是n = Integer.MAX_VALUE,我们都说它是O(1)。如果算法在每次输入大小加倍时花费的时间更长,那么我们说它是O(logn)

编辑:回答关于O(1)和O(logn)之间差异的具体问题,我举一个例子。假设我们想要一个能够在未排序数组中找到min元素的算法。一种方法是遍历每个元素并跟踪当前最小值。另一种方法是对数组进行排序,然后返回第一个元素。

第一个算法是O(n),第二个算法是O(nlogn)。所以我们假设我们从一个包含16个元素的数组开始。第一个算法将在时间16中运行,第二个算法将在时间16 * 4中运行。如果我们将它增加到17,那么它将变为17和17 * 4。我们可能天真地说第二种算法需要的时间是第一种算法的4倍(如果我们将logn组件视为常量)。

但是让我们来看看当我们的数组包含2 ^ 32个元素时会发生什么。现在第一个算法需要2 ^ 32次才能完成,其中我们的第二个算法需要32 * 2 ^ 32的时间才能完成。它需要32倍的时间。是的,这是一个小的差异,但它仍然是一个区别。如果第一个算法需要1分钟,第二个算法将花费半个多小时!

答案 3 :(得分:3)

我认为如果它被称为 O(n^0) ,你会得到一个更好的主意。

这是缩放功能,具体取决于输入变量N。这是一个函数,而不是数字,你永远不应该为变量N假设任何数字。

就像你说一个函数f(x)是3因为f(100) = 3,这是错误的。这是一个功能,而不是任何特定的数字。常量函数f(x) = 1仍然是函数,它永远不会等于另一个函数g(x) = N,即g(x)=f(x)

答案 4 :(得分:2)

您希望了解的增长率。 O(1)意味着根本没有增长。虽然O(logn)确实有增长。即使增长很小,它仍然是增长。

答案 5 :(得分:1)

你的想法不够大。在计算机上运行的任何算法都将永久运行或在一些少量步骤后终止 - 因为计算机只是一个有限状态机,你不能编写运行任意时间然后终止的算法。根据这一论点,Big-O符号只是理论上的,在现实生活中的计算机程序中没有任何意义。即使O(2^n)达到O(2^INT_MAX)的上限,也相当于O(1)

但实际上,如果您了解常数因素,Big-O 可以帮助您。即使算法的上限为O(log n)n也可能有32位,这可能意味着请求需要1秒到32秒。

答案 6 :(得分:1)

Big-O显示运行时间(或内存等)如何随着问题大小的变化而变化。 当问题的大小变大10倍时,O(n)解决方案需要10倍的时间,O(log(n))解决方案需要更长的时间,而O(1)解决方案需要相同的时间:O( 1)意味着“变化与常数1一样快”,但常数不会改变。

熟悉big-O notation in a bit more detail

答案 7 :(得分:0)

有一个原因让你留下“O(n)”,并考虑删掉“O(log n)”。 两者都是“常数”:前者小于32,后者小于2 32 。但你仍然有一种自然的感觉,你不能称之为O(n)O(1)。

但是,如果log(n) < 32,则意味着O(n * logn)算法比其O(n)版本慢<32> 。足够大写“log * n”s?