最近在一次采访中,我被问到了几个与技术问题过程中出现的各种算法的Big-O有关的问题。我不认为我在这方面做得很好......自从我参加编程课程以来我被要求计算算法的Big-O十年以来,我没有一个关于任何东西的'Big-O'的讨论我一直在努力或设计。我参与了许多与其他团队成员的讨论以及与我一起工作过的关于代码复杂性和速度的架构师的讨论,但我从未参与过在实际项目中实际使用Big-O计算的团队。讨论总是“考虑到我们对数据的理解,有更好或更有效的方法吗?”从来没有“这个算法的复杂性是什么”?
我想知道人们是否真的在真实的单词中讨论过他们代码的“Big-O”?
答案 0 :(得分:19)
使用它并没有那么多,你更了解它的含义。
有些程序员没有意识到使用O(N ^ 2)排序算法的后果。
我怀疑除了那些在学术界工作的人会在日常生活中使用Big-O复杂性分析。
答案 1 :(得分:11)
没有不必要的n平方
根据我的经验,你没有很多关于它的讨论,因为它不需要讨论。在实践中,根据我的经验,所有发生的事情是你发现某些东西很慢并且看到它是O(n ^ 2)实际上它可能是O(n log n)或O(n),然后你去了更改。除了“那是n平方,去解决它”之外没有其他讨论。
所以是的,根据我的经验你很常用它,但只是在“减少多项式的顺序”的基本意义上,而不是在一些高度调整的分析中“是的,但如果我们切换到这个疯狂算法,我们将从logN向下增加到Ackerman函数的反函数“或者一些这样的废话。任何小于多项式的东西,理论都会离开窗口并切换到分析(例如,甚至在O(n)和O(n log n)之间进行判断,测量实际数据)。
答案 2 :(得分:8)
Big-O符号相当理论化,而在实践中,您对实际的分析结果更感兴趣,这些结果会为您提供有关您的表现如何的难以理解的数字。
您可能有两种排序算法,书中有O(n^2)
和O(nlogn)
上限,但分析结果可能表明效率更高的算法可能会有一些开销(这在理论上没有反映出来)你找到它的约束)对于你正在处理的特定问题集,你可以选择理论上效率较低的排序算法。
底线:在现实生活中,分析结果通常优先于理论运行时界限。
答案 3 :(得分:6)
我一直这么做。当您必须处理“大”数字时,通常在我的情况下:用户,数据库中的行,促销代码等,您必须知道并考虑算法的Big-O。
例如,生成用于分发的随机促销代码的算法可用于生成数十亿个代码...使用O(N ^ 2)算法生成唯一代码意味着数周的CPU时间,而O(N )表示小时。
另一个典型的例子是代码中的查询(坏!)。人们查找表然后对每行执行查询...这将订单调到N ^ 2。您通常可以更改代码以正确使用SQL并获得N或NlogN的订单。
因此,根据我的经验,只有在使用正确的算法类之后,分析才有用。我使用分析来捕捉不良行为,例如理解为什么“小”数字绑定应用程序表现不佳。
答案 4 :(得分:5)
根据我个人经验的答案是 - 不。可能原因是我只使用简单易懂的算法和数据结构。几十年前,他们的复杂性分析已经完成并发表。 Rob Pike here更好地解释了为什么我们应该避免花哨的算法。简而言之,从业者几乎从不需要发明新算法,因此几乎不必使用Big-O。
那并不意味着你不应该精通Big-O。项目可能要求设计和分析一种全新的算法。对于一些现实世界的例子,请阅读Skiena的The Algorithm Design Manual中的“战争故事”。
答案 5 :(得分:3)
在某种程度上,我知道三个嵌套的for
- 循环可能比一个嵌套的for
循环更糟糕。换句话说,我用它作为参考直觉。
我从来没有在学术界之外计算出算法的Big-O。如果我有两种方法可以解决某个问题,如果我的直觉表明一个人的Big-O比另一个人要低,我可能会本能地选择较小的一个,而无需进一步分析。
另一方面,如果我知道某些大小 n 进入我的算法,并且我知道某些它相对较小(比如说,不到100个元素),我可能会把它看得最清晰(我想知道我的代码在编写完一个月之后会做什么)。毕竟,使用今天的计算机的用户几乎不会注意到100 ^ 2和100 ^ 3之间的差异(除非另有证明)。
但是,正如其他人所指出的那样,探查器有最后一个明确的说法:如果我编写的代码执行缓慢,我相信探查器比任何理论规则更多,并相应地修复。
答案 6 :(得分:2)
没有。我不会在“现实世界”的情况下使用Big-O复杂性。
我对整个问题的看法是这样的 - (也许是错误的......但这只是我的看法。)
Big-O复杂性的东西最终是要了解算法的效率。如果从经验或其他方式,你了解你正在处理的算法,并能够在正确的地方使用正确的算法,这就是最重要的。
如果你知道这个Big-O的东西,并且能够正确使用它,那就好了。
如果你不知道用数学的方式谈论算法及其效率 - Big-O的东西,但你知道真正重要的东西 - 在某种情况下使用的最佳算法 - 那就完美了。
如果你不知道,那就不好了。
答案 7 :(得分:2)
我试图推迟优化,直到分析数据证明它们是必需的。当然,除非在设计时显而易见,否则一种算法将比其他选项更有效(不会给项目增加太多的复杂性)。
答案 8 :(得分:2)
是的,我用它。不,它不经常“讨论”,就像我们不经常讨论“orderCount”或“xyz”是否是更好的变量名。
通常情况下,你不会坐下来分析它,但你会根据你所知道的内容产生直觉,而且几乎可以估计出O
- 复杂性在大多数情况下。
当我必须执行大量列表操作时,我通常会考虑一下。我是否正在做任何不必要的O(n^2)
复杂的事情,这可能是在线性时间内完成的?我在列表上多少次传球?这不是你需要进行正式分析的东西,但是如果不了解大O符号,那么准确地做起来会变得困难得多。
如果您希望软件在较大的输入尺寸上表现出令人满意的性能,那么您需要正式或非正式地考虑算法的大O复杂性。分析非常适合告诉您程序如何执行现在,但是如果您使用的是O(2^n)
算法,那么只要您的输入大小是,您的探查器就会告诉您一切都很好。小。然后您的输入大小增加,运行时爆炸。
人们经常将大O符号视为“理论”,或“无用”,或“不如剖析”。这只表明他们不了解的
Big-O复杂性主动告诉您如果在较大的输入上运行代码,哪些部分会爆炸。分析器无法告诉您。
答案 9 :(得分:1)
虽然您很少需要对一段代码进行深入的分析,但重要的是要了解它的含义,并能够快速评估您正在编写的代码的复杂性及其可能带来的后果。
在开发时,你经常觉得它“足够好”。呃,没有人会在这个数组中放置超过100个元素吗?然后,有一天,有人会在数组中放入1000个元素(信任用户:如果代码允许,其中一个将执行此操作)。而现在足够好的n ^ 2算法是一个很大的性能问题。
反过来它有时很有用:如果你知道你的功能必须进行n ^ 2操作并且你的算法的复杂性恰好是n ^ 3,那么你可以做些什么来使它成为n ^ 2。一旦它是n ^ 2,你将不得不进行较小的优化。
相反,如果您只是编写了一个排序算法并发现它具有线性复杂性,那么您可以确定它存在问题。 (当然,在现实生活中,你必须编写自己的排序算法的场合很少见,但我曾经在采访中看到有人对他的单一循环排序算法表示满意。)
答案 10 :(得分:1)
是的,对于服务器端代码,一个瓶颈可能意味着你无法扩展,因为无论你在一个问题上投入多少硬件,你的收益都会减少。
话虽如此,可伸缩性问题通常还有其他原因,例如阻止文件和网络访问,这比你看到的任何内部计算要慢得多,这就是分析比BigO更重要的原因。