【问题标题】:Do you use Big-O complexity evaluation in the 'real world'?您是否在“现实世界”中使用 Big-O 复杂度评估?
【发布时间】:2010-11-17 22:10:04
【问题描述】:

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

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

【问题讨论】:

    标签: performance algorithm profiling complexity-theory big-o


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      话虽如此,可伸缩性问题通常还有其他原因,例如阻塞文件和网络访问,这比您将看到的任何内部计算都慢得多,这就是为什么分析比 BigO 更重要的原因。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

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

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

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

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

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

          【讨论】:

            【解决方案5】:

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

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

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

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

            【讨论】:

              【解决方案6】:

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

              【讨论】:

                【解决方案7】:

                就我所知,三个嵌套的for-loop 可能比一个嵌套的for-loop 更糟糕。换句话说,我用它作为参考直觉。

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

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

                但是,正如其他人所指出的,分析器有最后的决定性意义:如果我编写的代码执行缓慢,我更信任分析器而不是任何理论规则,并相应地进行修复。

                【讨论】:

                  【解决方案8】:

                  没有不必要的 n 平方

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

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

                  【讨论】:

                  • 我会保留 logN 只是为了保持理智。
                  【解决方案9】:

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

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

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

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

                  【讨论】:

                    【解决方案10】:

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

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

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

                    【讨论】:

                    • 不过,在这种情况下,请小心使用真实数据进行分析。具有指数运行时间的算法对于小型数据集可能运行良好,但在超出一定范围时会发生灾难性的失败。这些是您可以通过事先分析捕捉到的东西,但取决于您如何准确地进行分析,仅通过分析可能很难检测到。
                    • @Johannes - 在现实生活中,您可以采取某些放松和假设,这些放松和假设根本不会反映在 Big-O 符号中
                    • 你在比较苹果和橘子。分析告诉您算法现在的执行情况。 Big-O 表示法告诉您当输入大小增加时它将如何扩展。相信分析告诉你这是幼稚的,并且会适得其反。如果您预计将来必须处理更大的问题规模,那么您几乎必须意识到大 O 复杂性。配置文件不会“优先”,它会告诉您完全不同的东西。两者在它们打算解决的情况下都很有价值。
                    【解决方案11】:

                    与其说是使用它,不如说是你了解其中的含义。

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

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

                    【讨论】:

                    • 我是这么想的,但采访真的归结为“告诉我这里使用什么算法?”和“该算法的复杂性是多少”。
                    • @Beggs:这些知识对于能够在每种情况下使用正确的算法是必要的。你怎么能在不知道它的复杂性的情况下选择合适的呢?
                    • @gs,我同意,但你能在采访中引用算法的 Big-O 吗?除了简单排序和树插入之类的事情之外,我还必须解决它。我知道合并排序比冒泡排序更好,但是当我开始谈论更复杂的事情时,我需要花一些时间来计算复杂度。
                    • 他们是在寻找实际的 BigO 值(如 8n-2)还是只是算法的顺序(如 O(n^2))?如果是第二个,那么计算嵌套循环有多“复杂”?如果是第一次 - 是的,这可能会浪费面试时间。
                    • 我经常使用它,但我也处理数百万的 N,所以 O(N) vs O(log N) 是巨大的。如果你的 N 很小,我怀疑你对它的使用会减少。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-03-16
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-04-30
                    • 1970-01-01
                    相关资源
                    最近更新 更多