16

最近在一次采访中,我被问到几个与技术问题过程中出现的各种算法的 Big-O 相关的问题。我不认为我在这方面做得很好......自从我参加编程课程以来,我们被要求计算算法的 Big-O 十年以来,我没有讨论过任何东西的“Big-O”我工作过或设计过。我与其他团队成员以及与我共事过的架构师就代码的复杂性和速度进行了许多讨论,但我从未加入过在实际项目中实际使用 Big-O 计算的团队。讨论总是“鉴于我们对数据的理解,是否有更好或更有效的方法来做到这一点?” 永远不要“这个算法的复杂性是多少”?

我想知道人们是否真的在讨论他们的代码中的“Big-O”?

4

11 回答 11

20

与其说是使用它,不如说是您了解其含义。

有些程序员没有意识到使用 O(N^2) 排序算法的后果。

我怀疑除了那些在学术界工作的人之外,还有很多人会在日常的愤怒中使用 Big-O 复杂性分析。

于 2009-08-08T10:24:04.200 回答
12

没有不必要的 n 平方

根据我的经验,您对此没有太多讨论,因为它不需要讨论。在实践中,根据我的经验,所发生的一切就是你发现某些东西很慢并且看到它是 O(n^2),而实际上它可能是 O(n log n) 或 O(n),然后你去更改。除了“这是n平方,去修复它”之外没有其他讨论。

所以是的,根据我的经验,你确实经常使用它,但只是在“降低多项式的阶数”的最基本意义上,而不是在一些高度调整的分析中“是的,但是如果我们切换到这个疯狂的算法,我们'会从 logN 增加到阿克曼函数的倒数' 或者一些这样的废话。任何小于多项式的东西,理论都消失了,你切换到分析(例如,甚至在 O(n) 和 O(n log n) 之间做出决定,测量真实数据)。

于 2009-08-08T10:45:47.290 回答
8

Big-O 表示法是相当理论上的,而在实践中,您对实际的分析结果更感兴趣,这会给您一个关于性能如何的硬数字。

您可能有两种排序算法,它们在书上都有O(n^2)上限O(nlogn),但是分析结果可能表明,效率更高的算法可能会有一些开销(这没有反映在您找到的理论界限中)并且对于您设置的特定问题正在处理,您可能会选择理论上效率较低的排序算法。

底线:在现实生活中,分析结果通常优先于理论运行时界限。

于 2009-08-08T10:26:14.180 回答
6

我会,一直。当您必须处理“大”数字时,通常在我的情况下:用户、数据库中的行、促销代码等,您必须了解并考虑算法的 Big-O。

例如,生成用于分发的随机促销代码的算法可用于生成数十亿个代码......使用 O(N^2) 算法生成唯一代码意味着数周的 CPU 时间,而 O(N) 意味着数小时.

另一个典型的例子是代码中的查询(糟糕!)。人们查找一个表,然后对每一行执行查询......这将顺序提高到 N^2。您通常可以更改代码以正确使用 SQL 并获得 N 或 NlogN 的订单。

因此,根据我的经验,分析只有在使用了正确的算法类之后才有用。我使用分析来捕捉不良行为,例如了解为什么“小”数量绑定的应用程序性能不佳。

于 2009-08-08T10:36:46.920 回答
5

根据我的个人经验,答案是 - 不。可能原因是我只使用简单、易于理解的算法和数据结构。几十年前,他们的复杂性分析已经完成并发表。Rob Pike在这里更好地解释了为什么我们应该避免花哨的算法。简而言之,从业者几乎不必发明新算法,因此几乎不必使用 Big-O。

好吧,这并不意味着您不应该精通 Big-O。一个项目可能需要设计和分析一种全新的算法。对于一些真实世界的例子,请阅读 Skiena 的算法设计手册中的“战争故事” 。

于 2009-08-08T10:32:30.080 回答
3

就我所知,三个嵌套for循环可能比一个嵌套循环差for。换句话说,我用它作为参考直觉。

我从未在学术界之外计算过算法的 Big-O。如果我有两种方法来解决某个问题,如果我的直觉表明其中一种的 Big-O 比另一种低,我可能会本能地采用较小的一种,而无需进一步分析。

另一方面,如果我确定进入我的算法的n的大小,并且我确定它相对较小(例如,在 100 个元素以下),我可能会选择最清晰的一个(我想知道我的代码在写完一个月后会做什么)。毕竟,使用当今计算机的用户几乎不会注意到 100^2 和 100^3 执行之间的差异(除非另有证明)。

但是,正如其他人所指出的那样,分析器有最后一个明确的说法:如果我编写的代码执行缓慢,我更信任分析器而不是任何理论规则,并相应地进行修复。

于 2009-08-08T11:01:53.170 回答
2

不,我不在“现实世界”的情况下使用 Big-O 复杂性。

我对整个问题的看法是这样的——(也许是错的……但这只是我的看法。)

Big-O 复杂性的东西最终是为了了解算法的效率。如果从经验或通过其他方式,您了解您正在处理的算法,并且能够在正确的地方使用正确的算法,这才是最重要的。

如果你知道这个 Big-O 的东西并且能够正确地使用它,那么很好。

如果您不知道以数学方式谈论算法及其效率——Big-O 的东西,但你知道真正重要的是什么——在某种情况下使用的最佳算法——那很好。

如果你也不知道,那就不好了。

于 2009-08-08T10:49:05.163 回答
2

我试图推迟优化,直到分析数据证明它们是必要的。当然,除非在设计时很明显,一种算法将比其他选项更有效(不会给项目增加太多复杂性)。

于 2009-08-08T11:35:03.853 回答
2

是的,我用它。不,它不经常“讨论”,就像我们不经常讨论“orderCount”或“xyz”是一个更好的变量名一样。

通常,你不会坐下来分析它,但你会根据你所知道的产生一种直觉,并且O在大多数情况下几乎可以动态估计 - 复杂性。

当我必须执行大量列表操作时,我通常会考虑一下。我是否在做任何O(n^2)本可以在线性时间内完成的不必要的复杂性工作?我在名单上做了多少次传球?这不是您需要进行正式分析的东西,但是如果没有大 O 表示法的知识,准确地做起来会变得更加困难。

如果您希望您的软件在较大的输入大小上能够以可接受的方式执行,那么您需要正式或非正式地考虑算法的大 O 复杂性。分析非常适合告诉您程序现在的执行情况,但是如果您使用O(2^n) 算法,则分析器会告诉您,只要您的输入很小,一切都很好。然后您的输入大小会增加,运行时会爆炸。

人们经常将大 O 表示法视为“理论上的”、“无用的”或“不如分析重要”。这只是表明他们不了解什么是大 O 复杂。它解决了与分析器不同的问题。两者对于编写具有良好性能的软件都是必不可少的。但分析最终是一种反应性工具。一旦问题存在,它就会告诉您问题出在哪里。

Big-O 复杂性会主动告诉您,如果您在较大的输入上运行它,您的代码的哪些部分将会崩溃。探查器无法告诉您。

于 2009-08-08T12:57:56.113 回答
1

尽管您很少需要对一段代码进行深入的 big-o 分析,但了解它的含义并能够快速评估您正在编写的代码的复杂性以及它可能产生的后果是很重要的。

在开发时,您经常觉得它“足够好”。呃,没有人会在这个数组中放入超过 100 个元素,对吧?然后,有一天,有人会将 1000 个元素放入数组中(相信用户:如果代码允许,其中一个会这样做)。而现在已经足够好的 n^2 算法是一个很大的性能问题。

有时反过来也很有用:如果你知道你必须进行 n^2 操作并且你的算法的复杂度恰好是 n^3,那么你可能可以做一些事情来使它成为 n^2。一旦达到 n^2,您将不得不进行较小的优化。

相反,如果你只是写了一个排序算法,发现它具有线性复杂度,你可以确定它有问题。(当然,在现实生活中,需要自己编写排序算法的情况很少见,但我曾经在一次采访中看到有人对他的一个 for 循环排序算法非常满意)。

于 2009-08-08T12:22:49.160 回答
1

是的,对于服务器端代码,一个瓶颈可能意味着您无法扩展,因为无论您为一个问题投入多少硬件,您都会得到递减的回报。

That being said, there are often other reasons for scalability problems, such as blocking on file- and network-access, which are much slower than any internal computation you'll see, which is why profiling is more important than BigO.

于 2012-06-07T19:01:36.690 回答