Algorithm 通过分析算法的性能,可以通过编程方式找到算法的bigO吗?

Algorithm 通过分析算法的性能,可以通过编程方式找到算法的bigO吗?,algorithm,language-agnostic,complexity-theory,big-o,Algorithm,Language Agnostic,Complexity Theory,Big O,请注意,我没有“问题”,我也不是在寻找“另一种方法来找到我的算法的大O” 我想知道的是,是否有可能编写一个程序,向其中传递数据点,这些数据点都是针对不同输入大小的算法的性能度量:(n,为n求解问题所花费的时间),然后确定算法的复杂度 例如,这里的输入可以是什么(可以大得多,这只是一个示例,这不是问题的重点): 使用这样的数据,是否有可能编写一个程序来判断我们是否有,比如说,一个O(n),log(n),nlog(n)或n算法?我想你可以用回归来近似它,但不能得到精确的结果。这是因为大多数算法的性能

请注意,我没有“问题”,我也不是在寻找“另一种方法来找到我的算法的大O”

我想知道的是,是否有可能编写一个程序,向其中传递数据点,这些数据点都是针对不同输入大小的算法的性能度量:
(n,为n求解问题所花费的时间)
,然后确定算法的复杂度

例如,这里的输入可以是什么(可以大得多,这只是一个示例,这不是问题的重点):


使用这样的数据,是否有可能编写一个程序来判断我们是否有,比如说,一个
O(n)
log(n)
nlog(n)
n算法?

我想你可以用回归来近似它,但不能得到精确的结果。这是因为大多数算法的性能取决于输入的内容(而不仅仅是大小)。因此,要完全理解这一点,您需要源代码。

您要查找的是。我所知道的解决这个问题的所有简单算法都会尝试将数据点拟合成某种多项式,但我怀疑也有一些算法能够区分多项式和非多项式。

您可以使用曲线拟合(请参见@Max S.)来确定描述数据的公式。然而,这只是故事的一半,因为无法知道数据是否充分描述了您的算法

例如,当n<100000000时,您的算法可能会呈现线性行为,然后开始以二次方式运行。如果您没有n>100000000的数据点,那么您的分析程序将无法给出正确答案


因此,总而言之,您可以通过编程实现,但结果仅限于示例中的数据点。而且没有算法方法来确定样本是否充分覆盖了所有“有趣”的点。

大多数big-O都是一台理想化的机器,具有无限内存,访问时间一致,不受其他应用程序的影响,等等。特别是当您超过缓存大小、主内存大小等阈值时(调进/调出交换文件)可能会对性能产生重大影响。因此,您确定的是算法在现实世界中的执行情况,而不是理想化的运行时间。

如果您试图根据经验估算big-O,则必须非常小心,以确保您在各种大小的大量实例上进行测试。请记住,big-O是最差的-案例概念。除了少数病理病例外,几乎所有病例都能找到性能良好的算法并不少见,但正是这些病理病例决定了大O时间。也就是说,如果你在抽样中错过了病理病例,你可能会认为O(2^n)算法是O(n)


如果你真正需要的是大O时间,而不仅仅是一个平均性能的概念,那么我建议用分析的方法证明它。如果不这样做,你就不能确定你没有错过一些病理输入。

你当然也可以做,例如指数回归()+1,曲线拟合似乎确实是我想要的。+1对Matthew too来说,他的链接也很有趣。请注意,这不一定会给你算法的大O性能,这是n->无穷大的渐近行为。有时低阶项应用于
n
,这在当时看起来相当大。@Mike:当然,但它会对于您最关心的区域,我仍然会给出一个合理的近似值,而复杂度在远点上分支的算法通常很容易发现。您可能希望使用不同的随机数据多次尝试每个输入大小。此外,您还可以测量低级计算的数量(例如,如果您正在研究排序算法,则元素比较的数量)而不是时间。您的扩展必须考虑到您的系统中存在一些限制,这些限制在通过时会导致根本性的变化。例如:能够适应cpu缓存而不是cpu缓存,能够适应物理内存或交换到磁盘,能够分发到更多的内核而不是。您需要了解这些限制才能查看它们对数据的影响。
    36 000 took 16 ms
   109 000 took 21 ms
   327 000 took 68 ms
   984 000 took 224 ms
 2 952 000 took 760 ms
 8 857 000 took 2305 ms
26 571 000 took 7379 ms
79 716 000 took 23336 ms